aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-06-16 21:03:24 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-06-16 21:03:24 +0000
commit7c7aba6e5fef47a01a136be655b0a92cfd7090f6 (patch)
tree99ec531924f6078534b100ab9d7696abce848099
parent7ab83427af0f77b59941ceba41d509d7d097b065 (diff)
downloadsrc-7c7aba6e5fef47a01a136be655b0a92cfd7090f6.tar.gz
src-7c7aba6e5fef47a01a136be655b0a92cfd7090f6.zip
Vendor import of llvm trunk r305575:vendor/llvm/llvm-trunk-r305575
Notes
Notes: svn path=/vendor/llvm/dist/; revision=320013 svn path=/vendor/llvm/llvm-trunk-r305575/; revision=320014; tag=vendor/llvm/llvm-trunk-r305575
-rw-r--r--cmake/modules/TableGen.cmake50
-rw-r--r--docs/BranchWeightMetadata.rst14
-rw-r--r--docs/LangRef.rst241
-rw-r--r--docs/Lexicon.rst7
-rw-r--r--docs/Phabricator.rst3
-rw-r--r--include/llvm/ADT/AllocatorList.h61
-rw-r--r--include/llvm/ADT/ArrayRef.h44
-rw-r--r--include/llvm/ADT/BreadthFirstIterator.h11
-rw-r--r--include/llvm/ADT/DAGDeltaAlgorithm.h10
-rw-r--r--include/llvm/ADT/DeltaAlgorithm.h10
-rw-r--r--include/llvm/ADT/DenseMap.h74
-rw-r--r--include/llvm/ADT/DenseMapInfo.h40
-rw-r--r--include/llvm/ADT/DenseSet.h46
-rw-r--r--include/llvm/ADT/DepthFirstIterator.h23
-rw-r--r--include/llvm/ADT/EquivalenceClasses.h22
-rw-r--r--include/llvm/ADT/FoldingSet.h233
-rw-r--r--include/llvm/ADT/GraphTraits.h15
-rw-r--r--include/llvm/ADT/ImmutableList.h8
-rw-r--r--include/llvm/ADT/ImmutableMap.h62
-rw-r--r--include/llvm/ADT/ImmutableSet.h121
-rw-r--r--include/llvm/ADT/IndexedMap.h18
-rw-r--r--include/llvm/ADT/IntervalMap.h49
-rw-r--r--include/llvm/ADT/IntrusiveRefCntPtr.h18
-rw-r--r--include/llvm/ADT/MapVector.h24
-rw-r--r--include/llvm/ADT/Optional.h33
-rw-r--r--include/llvm/ADT/PackedVector.h6
-rw-r--r--include/llvm/ADT/PointerEmbeddedInt.h30
-rw-r--r--include/llvm/ADT/PointerUnion.h2
-rw-r--r--include/llvm/ADT/ScopedHashTable.h12
-rw-r--r--include/llvm/ADT/SmallBitVector.h58
-rw-r--r--include/llvm/ADT/SmallSet.h7
-rw-r--r--include/llvm/ADT/StringExtras.h12
-rw-r--r--include/llvm/ADT/Triple.h4
-rw-r--r--include/llvm/ADT/ilist_base.h6
-rw-r--r--include/llvm/ADT/ilist_iterator.h59
-rw-r--r--include/llvm/ADT/ilist_node.h50
-rw-r--r--include/llvm/ADT/iterator.h8
-rw-r--r--include/llvm/ADT/simple_ilist.h33
-rw-r--r--include/llvm/Analysis/MemorySSA.h6
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h32
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h14
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h4
-rw-r--r--include/llvm/Analysis/TypeMetadataUtils.h7
-rw-r--r--include/llvm/Analysis/ValueTracking.h4
-rw-r--r--include/llvm/BinaryFormat/ELF.h38
-rw-r--r--include/llvm/Bitcode/BitcodeReader.h20
-rw-r--r--include/llvm/Bitcode/BitcodeWriter.h4
-rw-r--r--include/llvm/Bitcode/LLVMBitCodes.h8
-rw-r--r--include/llvm/CodeGen/BasicTTIImpl.h4
-rw-r--r--include/llvm/CodeGen/FunctionLoweringInfo.h12
-rw-r--r--include/llvm/CodeGen/GlobalISel/LegalizerHelper.h8
-rw-r--r--include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h24
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h19
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h6
-rw-r--r--include/llvm/CodeGen/TargetLoweringObjectFileImpl.h15
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeView.h5
-rw-r--r--include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h1
-rw-r--r--include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h7
-rw-r--r--include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h80
-rw-r--r--include/llvm/DebugInfo/CodeView/Formatters.h17
-rw-r--r--include/llvm/DebugInfo/CodeView/StringsAndChecksums.h106
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecord.h10
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndex.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h4
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFVerifier.h28
-rw-r--r--include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h4
-rw-r--r--include/llvm/DebugInfo/PDB/Native/DbiModuleList.h2
-rw-r--r--include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h9
-rw-r--r--include/llvm/DebugInfo/PDB/Native/InfoStream.h1
-rw-r--r--include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h9
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBFile.h2
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBStringTable.h2
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h5
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PublicsStream.h1
-rw-r--r--include/llvm/DebugInfo/PDB/Native/RawConstants.h6
-rw-r--r--include/llvm/DebugInfo/PDB/Native/SymbolStream.h4
-rw-r--r--include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h2
-rw-r--r--include/llvm/IR/Constants.h9
-rw-r--r--include/llvm/IR/DebugInfoMetadata.h3
-rw-r--r--include/llvm/IR/GlobalVariable.h2
-rw-r--r--include/llvm/IR/IRBuilder.h24
-rw-r--r--include/llvm/IR/InstrTypes.h8
-rw-r--r--include/llvm/IR/Instructions.h29
-rw-r--r--include/llvm/IR/IntrinsicInst.h90
-rw-r--r--include/llvm/IR/Intrinsics.td15
-rw-r--r--include/llvm/IR/ModuleSummaryIndex.h26
-rw-r--r--include/llvm/IR/ModuleSummaryIndexYAML.h18
-rw-r--r--include/llvm/IR/Operator.h1
-rw-r--r--include/llvm/IR/PatternMatch.h36
-rw-r--r--include/llvm/LTO/LTO.h33
-rw-r--r--include/llvm/LTO/legacy/LTOModule.h2
-rw-r--r--include/llvm/MC/MCSymbolWasm.h6
-rw-r--r--include/llvm/MC/MCWasmObjectWriter.h15
-rw-r--r--include/llvm/Object/ArchiveWriter.h1
-rw-r--r--include/llvm/Object/WindowsResource.h12
-rw-r--r--include/llvm/ObjectYAML/COFFYAML.h4
-rw-r--r--include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h25
-rw-r--r--include/llvm/ObjectYAML/CodeViewYAMLTypes.h3
-rw-r--r--include/llvm/Option/Arg.h15
-rw-r--r--include/llvm/Option/ArgList.h52
-rw-r--r--include/llvm/Option/OptSpecifier.h40
-rw-r--r--include/llvm/Option/OptTable.h19
-rw-r--r--include/llvm/Option/Option.h15
-rw-r--r--include/llvm/Support/BinaryStreamArray.h6
-rw-r--r--include/llvm/Support/DebugCounter.h6
-rw-r--r--include/llvm/Support/FormatAdapters.h13
-rw-r--r--include/llvm/Support/FormatCommon.h20
-rw-r--r--include/llvm/Support/MathExtras.h107
-rw-r--r--include/llvm/Support/ThreadPool.h28
-rw-r--r--include/llvm/TableGen/Main.h10
-rw-r--r--include/llvm/TableGen/Record.h150
-rw-r--r--include/llvm/TableGen/SetTheory.h6
-rw-r--r--include/llvm/TableGen/StringMatcher.h9
-rw-r--r--include/llvm/Target/TargetLoweringObjectFile.h7
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h10
-rw-r--r--include/llvm/Testing/Support/Error.h69
-rw-r--r--include/llvm/Testing/Support/SupportHelpers.h47
-rw-r--r--include/llvm/Transforms/Scalar/GVNExpression.h5
-rw-r--r--include/llvm/Transforms/Utils/CodeExtractor.h21
-rw-r--r--include/llvm/Transforms/Utils/Mem2Reg.h2
-rw-r--r--lib/Analysis/BasicAliasAnalysis.cpp22
-rw-r--r--lib/Analysis/CallGraphSCCPass.cpp8
-rw-r--r--lib/Analysis/DivergenceAnalysis.cpp2
-rw-r--r--lib/Analysis/MemorySSA.cpp2
-rw-r--r--lib/Analysis/ScalarEvolution.cpp129
-rw-r--r--lib/Analysis/TargetTransformInfo.cpp4
-rw-r--r--lib/Analysis/ValueTracking.cpp5
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp87
-rw-r--r--lib/Bitcode/Reader/MetadataLoader.cpp123
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp52
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h7
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfExpression.cpp33
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfExpression.h3
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.cpp6
-rw-r--r--lib/CodeGen/CodeGenPrepare.cpp2
-rw-r--r--lib/CodeGen/GlobalISel/LegalizerHelper.cpp81
-rw-r--r--lib/CodeGen/GlobalISel/MachineIRBuilder.cpp18
-rw-r--r--lib/CodeGen/MachineBlockPlacement.cpp10
-rw-r--r--lib/CodeGen/MachineLICM.cpp7
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp62
-rw-r--r--lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp26
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp15
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp21
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp18
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp61
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp79
-rw-r--r--lib/CodeGen/SplitKit.cpp3
-rw-r--r--lib/CodeGen/StackColoring.cpp237
-rw-r--r--lib/CodeGen/TargetLoweringBase.cpp28
-rw-r--r--lib/CodeGen/TargetLoweringObjectFileImpl.cpp49
-rw-r--r--lib/DebugInfo/CodeView/CMakeLists.txt3
-rw-r--r--lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp5
-rw-r--r--lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp2
-rw-r--r--lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp37
-rw-r--r--lib/DebugInfo/CodeView/StringsAndChecksums.cpp55
-rw-r--r--lib/DebugInfo/CodeView/SymbolDumper.cpp8
-rw-r--r--lib/DebugInfo/CodeView/SymbolRecordMapping.cpp4
-rw-r--r--lib/DebugInfo/CodeView/TypeDatabase.cpp71
-rw-r--r--lib/DebugInfo/CodeView/TypeIndex.cpp81
-rw-r--r--lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp2
-rw-r--r--lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp7
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp249
-rw-r--r--lib/DebugInfo/DWARF/DWARFDebugFrame.cpp23
-rw-r--r--lib/DebugInfo/DWARF/DWARFVerifier.cpp34
-rw-r--r--lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp2
-rw-r--r--lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp34
-rw-r--r--lib/DebugInfo/PDB/Native/InfoStream.cpp4
-rw-r--r--lib/DebugInfo/PDB/Native/PDBFile.cpp10
-rw-r--r--lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp10
-rw-r--r--lib/DebugInfo/PDB/Native/PDBStringTable.cpp3
-rw-r--r--lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp5
-rw-r--r--lib/DebugInfo/PDB/Native/PublicsStream.cpp9
-rw-r--r--lib/DebugInfo/PDB/Native/TpiHashing.cpp1
-rw-r--r--lib/DebugInfo/PDB/UDTLayout.cpp5
-rw-r--r--lib/Fuzzer/FuzzerDriver.cpp4
-rw-r--r--lib/Fuzzer/FuzzerLoop.cpp4
-rw-r--r--lib/Fuzzer/FuzzerTracePC.cpp23
-rw-r--r--lib/Fuzzer/FuzzerTracePC.h35
-rw-r--r--lib/Fuzzer/test/AbsNegAndConstant64Test.cpp2
-rw-r--r--lib/Fuzzer/test/CMakeLists.txt3
-rw-r--r--lib/Fuzzer/test/FourIndependentBranchesTest.cpp1
-rw-r--r--lib/Fuzzer/test/FuzzerUnittest.cpp12
-rw-r--r--lib/Fuzzer/test/ShrinkControlFlowTest.cpp1
-rw-r--r--lib/Fuzzer/test/SimpleHashTest.cpp2
-rw-r--r--lib/Fuzzer/test/SingleStrncmpTest.cpp1
-rw-r--r--lib/Fuzzer/test/TableLookupTest.cpp3
-rw-r--r--lib/Fuzzer/test/fuzzer-dirs.test8
-rw-r--r--lib/Fuzzer/test/inline-8bit-counters.test4
-rw-r--r--lib/Fuzzer/test/inline-8bit-counters/CMakeLists.txt12
-rw-r--r--lib/Fuzzer/test/trace-pc/CMakeLists.txt3
-rw-r--r--lib/IR/ConstantFold.cpp9
-rw-r--r--lib/IR/ConstantsContext.h18
-rw-r--r--lib/IR/DebugInfoMetadata.cpp28
-rw-r--r--lib/IR/IRBuilder.cpp15
-rw-r--r--lib/IR/Metadata.cpp2
-rw-r--r--lib/IR/ModuleSummaryIndex.cpp13
-rw-r--r--lib/IR/Verifier.cpp39
-rw-r--r--lib/LLVMBuild.txt1
-rw-r--r--lib/LTO/LTO.cpp200
-rw-r--r--lib/LTO/LTOModule.cpp12
-rw-r--r--lib/MC/MCParser/ELFAsmParser.cpp2
-rw-r--r--lib/MC/MCSectionELF.cpp2
-rw-r--r--lib/MC/WasmObjectWriter.cpp43
-rw-r--r--lib/Object/ArchiveWriter.cpp14
-rw-r--r--lib/Object/ELF.cpp1
-rw-r--r--lib/Object/IRSymtab.cpp6
-rw-r--r--lib/Object/WindowsResource.cpp156
-rw-r--r--lib/ObjectYAML/COFFYAML.cpp11
-rw-r--r--lib/ObjectYAML/CodeViewYAMLDebugSections.cpp338
-rw-r--r--lib/ObjectYAML/CodeViewYAMLSymbols.cpp64
-rw-r--r--lib/ObjectYAML/CodeViewYAMLTypes.cpp40
-rw-r--r--lib/ObjectYAML/ELFYAML.cpp1
-rw-r--r--lib/Option/Arg.cpp10
-rw-r--r--lib/Option/ArgList.cpp21
-rw-r--r--lib/Option/OptTable.cpp40
-rw-r--r--lib/Option/Option.cpp10
-rw-r--r--lib/Passes/PassBuilder.cpp6
-rw-r--r--lib/Support/BinaryStreamWriter.cpp4
-rw-r--r--lib/Support/DebugCounter.cpp6
-rw-r--r--lib/Support/FoldingSet.cpp42
-rw-r--r--lib/Support/ThreadPool.cpp19
-rw-r--r--lib/Support/Unix/Program.inc10
-rw-r--r--lib/TableGen/Record.cpp43
-rw-r--r--lib/TableGen/SetTheory.cpp20
-rw-r--r--lib/Target/AArch64/AArch64.td1
-rw-r--r--lib/Target/AArch64/AArch64FastISel.cpp8
-rw-r--r--lib/Target/AArch64/AArch64ISelLowering.cpp2
-rw-r--r--lib/Target/AArch64/AArch64SchedFalkorDetails.td61
-rw-r--r--lib/Target/AArch64/AArch64Subtarget.cpp4
-rw-r--r--lib/Target/AArch64/AArch64TargetTransformInfo.h2
-rw-r--r--lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp2
-rw-r--r--lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp2
-rw-r--r--lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp34
-rw-r--r--lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp10
-rw-r--r--lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp2
-rw-r--r--lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp15
-rw-r--r--lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h3
-rw-r--r--lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp21
-rw-r--r--lib/Target/AMDGPU/FLATInstructions.td77
-rw-r--r--lib/Target/AMDGPU/SIISelLowering.cpp14
-rw-r--r--lib/Target/AMDGPU/SIInstrInfo.cpp19
-rw-r--r--lib/Target/AMDGPU/SIInstrInfo.td12
-rw-r--r--lib/Target/ARM/ARMCallLowering.cpp55
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td18
-rw-r--r--lib/Target/ARM/ARMLegalizerInfo.cpp45
-rw-r--r--lib/Target/ARM/ARMTargetTransformInfo.h2
-rw-r--r--lib/Target/BPF/BPFAsmPrinter.cpp5
-rw-r--r--lib/Target/BPF/BPFISelDAGToDAG.cpp240
-rw-r--r--lib/Target/BPF/BPFInstrInfo.td14
-rw-r--r--lib/Target/Hexagon/HexagonGenMux.cpp52
-rw-r--r--lib/Target/Hexagon/HexagonISelDAGToDAG.cpp15
-rw-r--r--lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp3
-rw-r--r--lib/Target/Hexagon/HexagonPatterns.td19
-rw-r--r--lib/Target/Hexagon/HexagonTargetMachine.cpp8
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp135
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp9
-rw-r--r--lib/Target/Mips/MipsLongBranch.cpp12
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.cpp99
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.h3
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.cpp176
-rw-r--r--lib/Target/Mips/MipsSubtarget.h2
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp26
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp118
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h22
-rw-r--r--lib/Target/PowerPC/PPCInstr64Bit.td10
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp2
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td13
-rw-r--r--lib/Target/PowerPC/PPCInstrVSX.td10
-rw-r--r--lib/Target/PowerPC/PPCRegisterInfo.cpp14
-rw-r--r--lib/Target/PowerPC/PPCRegisterInfo.h1
-rw-r--r--lib/Target/PowerPC/PPCTargetTransformInfo.cpp2
-rw-r--r--lib/Target/PowerPC/PPCTargetTransformInfo.h2
-rw-r--r--lib/Target/SystemZ/SystemZTargetTransformInfo.cpp2
-rw-r--r--lib/Target/SystemZ/SystemZTargetTransformInfo.h2
-rw-r--r--lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h4
-rw-r--r--lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp25
-rw-r--r--lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp10
-rw-r--r--lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp2
-rw-r--r--lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h2
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp218
-rw-r--r--lib/Target/X86/X86InstrAVX512.td2
-rw-r--r--lib/Target/X86/X86InstrFragmentsSIMD.td12
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp134
-rw-r--r--lib/Testing/CMakeLists.txt1
-rw-r--r--lib/Testing/LLVMBuild.txt19
-rw-r--r--lib/Testing/Support/CMakeLists.txt12
-rw-r--r--lib/Testing/Support/Error.cpp22
-rw-r--r--lib/Testing/Support/LLVMBuild.txt22
-rw-r--r--lib/Transforms/IPO/CrossDSOCFI.cpp11
-rw-r--r--lib/Transforms/IPO/Inliner.cpp53
-rw-r--r--lib/Transforms/IPO/LowerTypeTests.cpp166
-rw-r--r--lib/Transforms/IPO/PartialInlining.cpp414
-rw-r--r--lib/Transforms/IPO/PassManagerBuilder.cpp6
-rw-r--r--lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp50
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp113
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp121
-rw-r--r--lib/Transforms/InstCombine/InstCombineInternal.h9
-rw-r--r--lib/Transforms/InstCombine/InstCombineShifts.cpp14
-rw-r--r--lib/Transforms/Instrumentation/CMakeLists.txt1
-rw-r--r--lib/Transforms/Instrumentation/IndirectCallPromotion.cpp353
-rw-r--r--lib/Transforms/Instrumentation/InstrProfiling.cpp12
-rw-r--r--lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp419
-rw-r--r--lib/Transforms/Instrumentation/SanitizerCoverage.cpp2
-rw-r--r--lib/Transforms/Scalar/CorrelatedValuePropagation.cpp2
-rw-r--r--lib/Transforms/Scalar/EarlyCSE.cpp5
-rw-r--r--lib/Transforms/Scalar/GVNSink.cpp11
-rw-r--r--lib/Transforms/Scalar/LoopIdiomRecognize.cpp24
-rw-r--r--lib/Transforms/Scalar/NewGVN.cpp4
-rw-r--r--lib/Transforms/Scalar/RewriteStatepointsForGC.cpp71
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp11
-rw-r--r--lib/Transforms/Utils/CodeExtractor.cpp219
-rw-r--r--lib/Transforms/Utils/PredicateInfo.cpp3
-rw-r--r--lib/Transforms/Utils/SimplifyIndVar.cpp14
-rw-r--r--test/Analysis/ScalarEvolution/limit-depth.ll44
-rw-r--r--test/Assembler/diexpression.ll14
-rw-r--r--test/Bitcode/DIExpression-deref.ll6
-rw-r--r--test/Bitcode/DIExpression-minus-upgrade.ll16
-rw-r--r--test/Bitcode/DIExpression-minus-upgrade.ll.bcbin0 -> 988 bytes
-rw-r--r--test/Bitcode/DIGlobalVariableExpression.ll2
-rw-r--r--test/Bitcode/upgrade-linker-options.ll15
-rw-r--r--test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir8
-rw-r--r--test/CodeGen/AArch64/arm64-sincos.ll50
-rw-r--r--test/CodeGen/AArch64/fast-isel-sp-adjust.ll288
-rw-r--r--test/CodeGen/AArch64/misched-fusion-aes.ll77
-rw-r--r--test/CodeGen/AArch64/sincos-expansion.ll42
-rw-r--r--test/CodeGen/AArch64/swifterror.ll27
-rw-r--r--test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir2
-rw-r--r--test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir2
-rw-r--r--test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir22
-rw-r--r--test/CodeGen/AMDGPU/always-uniform.ll21
-rw-r--r--test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll123
-rw-r--r--test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll4
-rw-r--r--test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir70
-rw-r--r--test/CodeGen/AMDGPU/flat-address-space.ll56
-rw-r--r--test/CodeGen/AMDGPU/flat_atomics.ll168
-rw-r--r--test/CodeGen/AMDGPU/global_smrd_cfg.ll33
-rw-r--r--test/CodeGen/AMDGPU/inserted-wait-states.mir10
-rw-r--r--test/CodeGen/AMDGPU/limit-coalesce.mir6
-rw-r--r--test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir4
-rw-r--r--test/CodeGen/AMDGPU/sdwa-scalar-ops.mir16
-rw-r--r--test/CodeGen/AMDGPU/waitcnt.mir22
-rw-r--r--test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll195
-rw-r--r--test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll21
-rw-r--r--test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir75
-rw-r--r--test/CodeGen/ARM/GlobalISel/arm-unsupported.ll8
-rw-r--r--test/CodeGen/ARM/cortex-a57-misched-vfma.ll38
-rw-r--r--test/CodeGen/ARM/debug-info-blocks.ll6
-rw-r--r--test/CodeGen/ARM/sincos.ll67
-rw-r--r--test/CodeGen/ARM/swifterror.ll28
-rw-r--r--test/CodeGen/BPF/rodata_1.ll52
-rw-r--r--test/CodeGen/BPF/rodata_2.ll51
-rw-r--r--test/CodeGen/BPF/rodata_3.ll41
-rw-r--r--test/CodeGen/BPF/rodata_4.ll43
-rw-r--r--test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll48
-rw-r--r--test/CodeGen/Hexagon/mulh.ll27
-rw-r--r--test/CodeGen/Hexagon/mux-kill.mir15
-rw-r--r--test/CodeGen/Hexagon/mux-kill2.mir17
-rw-r--r--test/CodeGen/Hexagon/store-imm-stack-object.ll86
-rw-r--r--test/CodeGen/Mips/2008-06-05-Carry.ll13
-rw-r--r--test/CodeGen/Mips/brundef.ll26
-rw-r--r--test/CodeGen/Mips/dsp-patterns.ll4
-rw-r--r--test/CodeGen/Mips/llcarry.ll11
-rw-r--r--test/CodeGen/Mips/llvm-ir/add.ll394
-rw-r--r--test/CodeGen/Mips/llvm-ir/sub.ll174
-rw-r--r--test/CodeGen/Mips/longbranch.ll40
-rw-r--r--test/CodeGen/Mips/madd-msub.ll81
-rw-r--r--test/CodeGen/PowerPC/atomic-2.ll2
-rw-r--r--test/CodeGen/PowerPC/atomics-constant.ll2
-rw-r--r--test/CodeGen/PowerPC/atomics-regression.ll20
-rw-r--r--test/CodeGen/PowerPC/licm-tocReg.ll110
-rw-r--r--test/CodeGen/PowerPC/logic-ops-on-compares.ll73
-rw-r--r--test/CodeGen/PowerPC/ppc64-P9-mod.ll263
-rw-r--r--test/CodeGen/PowerPC/testComparesinesll.ll125
-rw-r--r--test/CodeGen/PowerPC/testComparesineull.ll125
-rw-r--r--test/CodeGen/PowerPC/testComparesllnesll.ll125
-rw-r--r--test/CodeGen/PowerPC/testComparesllneull.ll125
-rw-r--r--test/CodeGen/PowerPC/vec_revb.ll54
-rw-r--r--test/CodeGen/SystemZ/fp-sincos-01.ll55
-rw-r--r--test/CodeGen/X86/2012-01-11-split-cv.ll3
-rw-r--r--test/CodeGen/X86/StackColoring.ll64
-rw-r--r--test/CodeGen/X86/add-sub-nsw-nuw.ll3
-rw-r--r--test/CodeGen/X86/addcarry.ll24
-rw-r--r--test/CodeGen/X86/avx-vperm2x128.ll20
-rw-r--r--test/CodeGen/X86/bt.ll209
-rw-r--r--test/CodeGen/X86/cmov-into-branch.ll24
-rw-r--r--test/CodeGen/X86/combine-64bit-vec-binop.ll23
-rw-r--r--test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll45
-rw-r--r--test/CodeGen/X86/fast-isel-select-sse.ll26
-rw-r--r--test/CodeGen/X86/fp-logic-replace.ll2
-rw-r--r--test/CodeGen/X86/fp-logic.ll23
-rw-r--r--test/CodeGen/X86/fp-select-cmp-and.ll20
-rw-r--r--test/CodeGen/X86/immediate_merging64.ll4
-rw-r--r--test/CodeGen/X86/lea-opt-with-debug.mir2
-rw-r--r--test/CodeGen/X86/loop-search.ll3
-rw-r--r--test/CodeGen/X86/mask-negated-bool.ll8
-rw-r--r--test/CodeGen/X86/memset-2.ll6
-rw-r--r--test/CodeGen/X86/memset-nonzero.ll12
-rw-r--r--test/CodeGen/X86/memset64-on-x86-32.ll3
-rw-r--r--test/CodeGen/X86/negate-i1.ll10
-rw-r--r--test/CodeGen/X86/negate-shift.ll6
-rw-r--r--test/CodeGen/X86/negate.ll8
-rw-r--r--test/CodeGen/X86/negative-sin.ll14
-rw-r--r--test/CodeGen/X86/no-sse2-avg.ll3
-rw-r--r--test/CodeGen/X86/not-and-simplify.ll1
-rw-r--r--test/CodeGen/X86/pr13577.ll8
-rw-r--r--test/CodeGen/X86/pr18014.ll3
-rw-r--r--test/CodeGen/X86/pr32368.ll153
-rw-r--r--test/CodeGen/X86/rem.ll8
-rw-r--r--test/CodeGen/X86/sar_fold64.ll8
-rw-r--r--test/CodeGen/X86/select-with-and-or.ll16
-rw-r--r--test/CodeGen/X86/sext-setcc-self.ll8
-rw-r--r--test/CodeGen/X86/shift-pcmp.ll4
-rw-r--r--test/CodeGen/X86/sincos-opt.ll137
-rw-r--r--test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll2
-rw-r--r--test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll10
-rw-r--r--test/CodeGen/X86/stack-folding-int-avx512.ll93
-rw-r--r--test/CodeGen/X86/stack-folding-int-avx512vl.ll74
-rw-r--r--test/CodeGen/X86/statepoint-live-in.ll8
-rw-r--r--test/CodeGen/X86/swifterror.ll108
-rw-r--r--test/CodeGen/X86/urem-i8-constant.ll3
-rw-r--r--test/CodeGen/X86/urem-power-of-two.ll7
-rw-r--r--test/CodeGen/X86/vec3.ll4
-rw-r--r--test/CodeGen/X86/vector-compare-combines.ll4
-rw-r--r--test/CodeGen/X86/vector-shuffle-256-v16.ll18
-rw-r--r--test/CodeGen/X86/vzero-excess.ll2
-rw-r--r--test/CodeGen/X86/x86-interleaved-access.ll44
-rw-r--r--test/DebugInfo/COFF/array-odr-violation.ll6
-rw-r--r--test/DebugInfo/COFF/inlining-same-name.ll3
-rw-r--r--test/DebugInfo/Generic/block-asan.ll4
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-str-offsets-dwp.x86_64.obin0 -> 3328 bytes
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-str-offsets.s250
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-test-zlib.cc3
-rw-r--r--test/DebugInfo/Inputs/dwarfdump-test-zlib.o.elf-x86-64bin0 -> 4688 bytes
-rw-r--r--test/DebugInfo/MIR/ARM/split-superreg-complex.mir2
-rw-r--r--test/DebugInfo/PDB/Inputs/unknown-symbol.yaml10
-rw-r--r--test/DebugInfo/PDB/pdb-unknown-symbol.test6
-rw-r--r--test/DebugInfo/PDB/pdb-yaml-types.test74
-rw-r--r--test/DebugInfo/PDB/pdbdump-debug-subsections.test146
-rw-r--r--test/DebugInfo/PDB/pdbdump-headers.test3971
-rw-r--r--test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test106
-rw-r--r--test/DebugInfo/PDB/pdbdump-mergeids.test43
-rw-r--r--test/DebugInfo/PDB/pdbdump-mergetypes.test60
-rw-r--r--test/DebugInfo/PDB/pdbdump-raw-blocks.test64
-rw-r--r--test/DebugInfo/PDB/pdbdump-raw-stream.test51
-rw-r--r--test/DebugInfo/PDB/pdbdump-readwrite.test73
-rw-r--r--test/DebugInfo/X86/block-capture.ll2
-rw-r--r--test/DebugInfo/X86/debug-info-block-captured-self.ll4
-rw-r--r--test/DebugInfo/X86/debug-info-blocks.ll2
-rw-r--r--test/DebugInfo/X86/double-declare.ll44
-rw-r--r--test/DebugInfo/X86/dw_op_minus.ll4
-rw-r--r--test/DebugInfo/X86/dw_op_minus_direct.ll2
-rw-r--r--test/DebugInfo/X86/safestack-byval.ll4
-rw-r--r--test/DebugInfo/X86/stack-value-dwarf2.ll2
-rw-r--r--test/DebugInfo/X86/unattached-global.ll2
-rw-r--r--test/DebugInfo/dwarfdump-str-offsets-dwp.test56
-rw-r--r--test/DebugInfo/dwarfdump-zlib.test5
-rw-r--r--test/Instrumentation/InstrProfiling/always_inline.ll28
-rw-r--r--test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll2
-rw-r--r--test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll16
-rw-r--r--test/LTO/Resolution/X86/dead-strip-fulllto.ll37
-rw-r--r--test/LTO/Resolution/X86/symtab-elf.ll4
-rw-r--r--test/LTO/Resolution/X86/symtab.ll4
-rw-r--r--test/LibDriver/use-paths.test24
-rw-r--r--test/MC/AMDGPU/flat-gfx9.s40
-rw-r--r--test/MC/AMDGPU/flat.s3
-rw-r--r--test/MC/COFF/cv-compiler-info.ll6
-rwxr-xr-xtest/MC/COFF/linker-options.ll8
-rw-r--r--test/MC/Disassembler/PowerPC/ppc64-encoding.txt12
-rw-r--r--test/MC/Disassembler/PowerPC/ppc64le-encoding.txt12
-rw-r--r--test/MC/ELF/section.s12
-rw-r--r--test/MC/MachO/linker-options.ll7
-rw-r--r--test/MC/PowerPC/ppc64-encoding.s13
-rw-r--r--test/MC/WebAssembly/external-data.ll4
-rw-r--r--test/MC/WebAssembly/external-func-address.ll25
-rw-r--r--test/MC/WebAssembly/func-address.ll48
-rw-r--r--test/ThinLTO/X86/cfi-icall.ll29
-rw-r--r--test/Transforms/CodeExtractor/live_shrink.ll67
-rw-r--r--test/Transforms/CodeExtractor/live_shrink_gep.ll66
-rw-r--r--test/Transforms/CodeExtractor/live_shrink_hoist.ll66
-rw-r--r--test/Transforms/CodeExtractor/live_shrink_multiple.ll66
-rw-r--r--test/Transforms/CodeExtractor/live_shrink_unsafe.ll94
-rw-r--r--test/Transforms/CrossDSOCFI/cfi_functions.ll23
-rw-r--r--test/Transforms/EarlyCSE/pr33406.ll26
-rw-r--r--test/Transforms/GVN/pr32314.ll53
-rw-r--r--test/Transforms/GlobalMerge/debug-info.ll2
-rw-r--r--test/Transforms/Inline/always-inline.ll11
-rw-r--r--test/Transforms/InstCombine/debuginfo-dce.ll12
-rw-r--r--test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll30
-rw-r--r--test/Transforms/InstCombine/ffs-1.ll156
-rw-r--r--test/Transforms/InstCombine/lshr.ll19
-rw-r--r--test/Transforms/InstCombine/onehot_merge.ll76
-rw-r--r--test/Transforms/InstCombine/or-xor.ll44
-rw-r--r--test/Transforms/InstCombine/select-with-bitwise-ops.ll268
-rw-r--r--test/Transforms/InstCombine/shift.ll10
-rw-r--r--test/Transforms/InstCombine/xor2.ll33
-rw-r--r--test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll36
-rw-r--r--test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll2
-rw-r--r--test/Transforms/LowerTypeTests/Inputs/import-icall.yaml19
-rw-r--r--test/Transforms/LowerTypeTests/export-icall.ll70
-rw-r--r--test/Transforms/LowerTypeTests/import-icall.ll40
-rw-r--r--test/Transforms/PGOProfile/memop_size_opt.ll9
-rw-r--r--test/Transforms/RewriteStatepointsForGC/drop-invalid-metadata.ll92
-rw-r--r--test/Transforms/SLPVectorizer/X86/arith-add.ll58
-rw-r--r--test/Transforms/SLPVectorizer/X86/arith-fp.ll180
-rw-r--r--test/Transforms/SLPVectorizer/X86/arith-mul.ll74
-rw-r--r--test/Transforms/SLPVectorizer/X86/arith-sub.ll58
-rw-r--r--test/Transforms/SafeStack/X86/debug-loc.ll4
-rw-r--r--test/Transforms/SafeStack/X86/debug-loc2.ll6
-rw-r--r--test/Transforms/Util/PredicateInfo/pr33456.ll68
-rw-r--r--test/Transforms/Util/PredicateInfo/pr33457.ll93
-rw-r--r--test/Verifier/element-wise-atomic-memory-intrinsics.ll20
-rw-r--r--test/lit.cfg2
-rw-r--r--test/tools/llvm-cvtres/Inputs/combined.obj.coffbin0 -> 4040 bytes
-rw-r--r--test/tools/llvm-cvtres/Inputs/languages.rc36
-rw-r--r--test/tools/llvm-cvtres/Inputs/languages.resbin0 -> 452 bytes
-rw-r--r--test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.armbin0 -> 3472 bytes
-rw-r--r--test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.x64bin0 -> 3472 bytes
-rw-r--r--test/tools/llvm-cvtres/basic.test4
-rw-r--r--test/tools/llvm-cvtres/combined.test313
-rw-r--r--test/tools/llvm-cvtres/help.test13
-rw-r--r--test/tools/llvm-cvtres/machine.test59
-rw-r--r--test/tools/llvm-cvtres/object.test227
-rw-r--r--test/tools/llvm-cvtres/parse.test2
-rw-r--r--test/tools/llvm-dwarfdump/X86/apple_names_verify_buckets.s192
-rw-r--r--test/tools/llvm-pdbdump/raw-stream-data.test47
-rw-r--r--test/tools/llvm-readobj/resources.test230
-rw-r--r--tools/llvm-ar/llvm-ar.cpp12
-rw-r--r--tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp2
-rw-r--r--tools/llvm-cvtres/llvm-cvtres.cpp16
-rw-r--r--tools/llvm-dwarfdump/llvm-dwarfdump.cpp1
-rw-r--r--tools/llvm-pdbutil/CMakeLists.txt5
-rw-r--r--tools/llvm-pdbutil/FormatUtil.cpp49
-rw-r--r--tools/llvm-pdbutil/FormatUtil.h120
-rw-r--r--tools/llvm-pdbutil/LLVMOutputStyle.cpp1188
-rw-r--r--tools/llvm-pdbutil/LinePrinter.cpp33
-rw-r--r--tools/llvm-pdbutil/LinePrinter.h31
-rw-r--r--tools/llvm-pdbutil/MinimalSymbolDumper.cpp749
-rw-r--r--tools/llvm-pdbutil/MinimalSymbolDumper.h47
-rw-r--r--tools/llvm-pdbutil/MinimalTypeDumper.cpp543
-rw-r--r--tools/llvm-pdbutil/MinimalTypeDumper.h61
-rw-r--r--tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp24
-rw-r--r--tools/llvm-pdbutil/RawOutputStyle.cpp1064
-rw-r--r--tools/llvm-pdbutil/RawOutputStyle.h (renamed from tools/llvm-pdbutil/LLVMOutputStyle.h)40
-rw-r--r--tools/llvm-pdbutil/YAMLOutputStyle.cpp34
-rw-r--r--tools/llvm-pdbutil/llvm-pdbutil.cpp217
-rw-r--r--tools/llvm-pdbutil/llvm-pdbutil.h49
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp45
-rw-r--r--tools/llvm-readobj/ELFDumper.cpp2
-rw-r--r--tools/llvm-stress/llvm-stress.cpp20
-rw-r--r--tools/obj2yaml/CMakeLists.txt1
-rw-r--r--tools/obj2yaml/coff2yaml.cpp57
-rw-r--r--tools/yaml2obj/CMakeLists.txt1
-rw-r--r--tools/yaml2obj/yaml2coff.cpp56
-rw-r--r--tools/yaml2obj/yaml2obj.cpp1
-rw-r--r--unittests/ADT/SCCIteratorTest.cpp6
-rw-r--r--unittests/ADT/SmallVectorTest.cpp20
-rw-r--r--unittests/ADT/StringRefTest.cpp3
-rw-r--r--unittests/CodeGen/LowLevelTypeTest.cpp3
-rw-r--r--unittests/DebugInfo/CodeView/CMakeLists.txt2
-rw-r--r--unittests/DebugInfo/CodeView/ErrorChecking.h70
-rw-r--r--unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp18
-rw-r--r--unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp1
-rw-r--r--unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp12
-rw-r--r--unittests/DebugInfo/PDB/CMakeLists.txt2
-rw-r--r--unittests/DebugInfo/PDB/ErrorChecking.h61
-rw-r--r--unittests/DebugInfo/PDB/HashTableTest.cpp10
-rw-r--r--unittests/DebugInfo/PDB/MSFBuilderTest.cpp101
-rw-r--r--unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp119
-rw-r--r--unittests/DebugInfo/PDB/StringTableBuilderTest.cpp19
-rw-r--r--unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp32
-rw-r--r--unittests/IR/MetadataTest.cpp14
-rw-r--r--unittests/IR/PatternMatch.cpp77
-rw-r--r--unittests/MI/LiveIntervalTest.cpp3
-rw-r--r--unittests/Support/BinaryStreamTest.cpp163
-rw-r--r--unittests/Support/CMakeLists.txt2
-rw-r--r--unittests/Support/CommandLineTest.cpp9
-rw-r--r--unittests/Support/DynamicLibrary/CMakeLists.txt4
-rw-r--r--unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp2
-rw-r--r--unittests/Support/DynamicLibrary/ExportedFuncs.cxx16
-rw-r--r--unittests/Support/DynamicLibrary/PipSqueak.cxx3
-rw-r--r--unittests/Support/DynamicLibrary/PipSqueak.h2
-rw-r--r--unittests/Support/FormatVariadicTest.cpp2
-rw-r--r--unittests/Target/AArch64/InstSizes.cpp15
-rw-r--r--unittests/Transforms/Scalar/LoopPassManagerTest.cpp11
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp4
-rwxr-xr-xutils/opt-viewer/opt-diff.py2
-rwxr-xr-xutils/opt-viewer/opt-stats.py2
-rwxr-xr-xutils/opt-viewer/opt-viewer.py2
-rwxr-xr-xutils/release/test-release.sh5
-rwxr-xr-xutils/update_test_checks.py96
595 files changed, 17845 insertions, 11359 deletions
diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake
index 17ae1c9e7717..21421e4fdbd2 100644
--- a/cmake/modules/TableGen.cmake
+++ b/cmake/modules/TableGen.cmake
@@ -35,38 +35,24 @@ function(tablegen project ofn)
# a tablegen change, as cmake does not propagate file-level dependencies
# of custom targets. See the following ticket for more information:
# https://cmake.org/Bug/view.php?id=15858
- # We could always have just one dependency on both the target and
- # the file, but these 2 cases would produce cleaner cmake files.
- if (${${project}_TABLEGEN_TARGET} STREQUAL ${${project}_TABLEGEN_EXE})
- add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
- # Generate tablegen output in a temporary file.
- COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
- ${LLVM_TABLEGEN_FLAGS}
- ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
- -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
- # The file in LLVM_TARGET_DEFINITIONS may be not in the current
- # directory and local_tds may not contain it, so we must
- # explicitly list it here:
- DEPENDS ${${project}_TABLEGEN_TARGET} ${local_tds} ${global_tds}
- ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
- COMMENT "Building ${ofn}..."
- )
- else()
- add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
- # Generate tablegen output in a temporary file.
- COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
- ${LLVM_TABLEGEN_FLAGS}
- ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
- -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
- # The file in LLVM_TARGET_DEFINITIONS may be not in the current
- # directory and local_tds may not contain it, so we must
- # explicitly list it here:
- DEPENDS ${${project}_TABLEGEN_TARGET} ${${project}_TABLEGEN_EXE}
- ${local_tds} ${global_tds}
- ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
- COMMENT "Building ${ofn}..."
- )
- endif()
+ # The dependency on both, the target and the file, produces the same
+ # dependency twice in the result file when
+ # ("${${project}_TABLEGEN_TARGET}" STREQUAL "${${project}_TABLEGEN_EXE}")
+ # but lets us having smaller and cleaner code here.
+ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
+ # Generate tablegen output in a temporary file.
+ COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
+ ${LLVM_TABLEGEN_FLAGS}
+ ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
+ -o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
+ # The file in LLVM_TARGET_DEFINITIONS may be not in the current
+ # directory and local_tds may not contain it, so we must
+ # explicitly list it here:
+ DEPENDS ${${project}_TABLEGEN_TARGET} ${${project}_TABLEGEN_EXE}
+ ${local_tds} ${global_tds}
+ ${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
+ COMMENT "Building ${ofn}..."
+ )
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
# Only update the real output file if there are any differences.
# This prevents recompilation of all the files depending on it if there
diff --git a/docs/BranchWeightMetadata.rst b/docs/BranchWeightMetadata.rst
index b941d0d15050..9bd8bd4ae744 100644
--- a/docs/BranchWeightMetadata.rst
+++ b/docs/BranchWeightMetadata.rst
@@ -64,6 +64,20 @@ Branch weights are assigned to every destination.
[ , i32 <LABEL_BRANCH_WEIGHT> ... ]
}
+``CallInst``
+^^^^^^^^^^^^^^^^^^
+
+Calls may have branch weight metadata, containing the execution count of
+the call. It is currently used in SamplePGO mode only, to augment the
+block and entry counts which may not be accurate with sampling.
+
+.. code-block:: none
+
+ !0 = metadata !{
+ metadata !"branch_weights",
+ i32 <CALL_BRANCH_WEIGHT>
+ }
+
Other
^^^^^
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index e063f6bd35fe..68aa500150ae 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -4033,26 +4033,26 @@ DICompileUnit
"""""""""""""
``DICompileUnit`` nodes represent a compile unit. The ``enums:``,
-``retainedTypes:``, ``subprograms:``, ``globals:``, ``imports:`` and ``macros:``
-fields are tuples containing the debug info to be emitted along with the compile
-unit, regardless of code optimizations (some nodes are only emitted if there are
-references to them from instructions). The ``debugInfoForProfiling:`` field is a
-boolean indicating whether or not line-table discriminators are updated to
-provide more-accurate debug info for profiling results.
+``retainedTypes:``, ``globals:``, ``imports:`` and ``macros:`` fields are tuples
+containing the debug info to be emitted along with the compile unit, regardless
+of code optimizations (some nodes are only emitted if there are references to
+them from instructions). The ``debugInfoForProfiling:`` field is a boolean
+indicating whether or not line-table discriminators are updated to provide
+more-accurate debug info for profiling results.
.. code-block:: text
!0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang",
isOptimized: true, flags: "-O2", runtimeVersion: 2,
splitDebugFilename: "abc.debug", emissionKind: FullDebug,
- enums: !2, retainedTypes: !3, subprograms: !4,
- globals: !5, imports: !6, macros: !7, dwoId: 0x0abcd)
+ enums: !2, retainedTypes: !3, globals: !4, imports: !5,
+ macros: !6, dwoId: 0x0abcd)
Compile unit descriptors provide the root scope for objects declared in a
-specific compilation unit. File descriptors are defined using this scope.
-These descriptors are collected by a named metadata ``!llvm.dbg.cu``. They
-keep track of subprograms, global variables, type information, and imported
-entities (declarations and namespaces).
+specific compilation unit. File descriptors are defined using this scope. These
+descriptors are collected by a named metadata node ``!llvm.dbg.cu``. They keep
+track of global variables, type information, and imported entities (declarations
+and namespaces).
.. _DIFile:
@@ -4326,8 +4326,8 @@ and ``scope:``.
containingType: !4,
virtuality: DW_VIRTUALITY_pure_virtual,
virtualIndex: 10, flags: DIFlagPrototyped,
- isOptimized: true, templateParams: !5,
- declaration: !6, variables: !7)
+ isOptimized: true, unit: !5, templateParams: !6,
+ declaration: !7, variables: !8, thrownTypes: !9)
.. _DILexicalBlock:
@@ -4404,7 +4404,12 @@ referenced LLVM variable relates to the source language variable.
The current supported vocabulary is limited:
- ``DW_OP_deref`` dereferences the top of the expression stack.
-- ``DW_OP_plus, 93`` adds ``93`` to the working expression.
+- ``DW_OP_plus`` pops the last two entries from the expression stack, adds
+ them together and appends the result to the expression stack.
+- ``DW_OP_minus`` pops the last two entries from the expression stack, subtracts
+ the last entry from the second last entry and appends the result to the
+ expression stack.
+- ``DW_OP_plus_uconst, 93`` adds ``93`` to the working expression.
- ``DW_OP_LLVM_fragment, 16, 8`` specifies the offset and size (``16`` and ``8``
here, respectively) of the variable fragment from the working expression. Note
that contrary to DW_OP_bit_piece, the offset is describing the the location
@@ -4426,9 +4431,10 @@ combined with a concrete location.
.. code-block:: llvm
!0 = !DIExpression(DW_OP_deref)
- !1 = !DIExpression(DW_OP_plus, 3)
+ !1 = !DIExpression(DW_OP_plus_uconst, 3)
+ !1 = !DIExpression(DW_OP_constu, 3, DW_OP_plus)
!2 = !DIExpression(DW_OP_bit_piece, 3, 7)
- !3 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
+ !3 = !DIExpression(DW_OP_deref, DW_OP_constu, 3, DW_OP_plus, DW_OP_LLVM_fragment, 3, 7)
!4 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
!5 = !DIExpression(DW_OP_constu, 42, DW_OP_stack_value)
@@ -5186,6 +5192,72 @@ Example:
!0 = !{i32* @a}
+'``prof``' Metadata
+^^^^^^^^^^^^^^^^^^^
+
+The ``prof`` metadata is used to record profile data in the IR.
+The first operand of the metadata node indicates the profile metadata
+type. There are currently 3 types:
+:ref:`branch_weights<prof_node_branch_weights>`,
+:ref:`function_entry_count<prof_node_function_entry_count>`, and
+:ref:`VP<prof_node_VP>`.
+
+.. _prof_node_branch_weights:
+
+branch_weights
+""""""""""""""
+
+Branch weight metadata attached to a branch, select, switch or call instruction
+represents the likeliness of the associated branch being taken.
+For more information, see :doc:`BranchWeightMetadata`.
+
+.. _prof_node_function_entry_count:
+
+function_entry_count
+""""""""""""""""""""
+
+Function entry count metadata can be attached to function definitions
+to record the number of times the function is called. Used with BFI
+information, it is also used to derive the basic block profile count.
+For more information, see :doc:`BranchWeightMetadata`.
+
+.. _prof_node_VP:
+
+VP
+""
+
+VP (value profile) metadata can be attached to instructions that have
+value profile information. Currently this is indirect calls (where it
+records the hottest callees) and calls to memory intrinsics such as memcpy,
+memmove, and memset (where it records the hottest byte lengths).
+
+Each VP metadata node contains "VP" string, then a uint32_t value for the value
+profiling kind, a uint64_t value for the total number of times the instruction
+is executed, followed by uint64_t value and execution count pairs.
+The value profiling kind is 0 for indirect call targets and 1 for memory
+operations. For indirect call targets, each profile value is a hash
+of the callee function name, and for memory operations each value is the
+byte length.
+
+Note that the value counts do not need to add up to the total count
+listed in the third operand (in practice only the top hottest values
+are tracked and reported).
+
+Indirect call example:
+
+.. code-block:: llvm
+
+ call void %f(), !prof !1
+ !1 = !{!"VP", i32 0, i64 1600, i64 7651369219802541373, i64 1030, i64 -4377547752858689819, i64 410}
+
+Note that the VP type is 0 (the second operand), which indicates this is
+an indirect call value profile data. The third operand indicates that the
+indirect call executed 1600 times. The 4th and 6th operands give the
+hashes of the 2 hottest target functions' names (this is the same hash used
+to represent function names in the profile database), and the 5th and 7th
+operands give the execution count that each of the respective prior target
+functions was called.
+
Module Flags Metadata
=====================
@@ -5352,40 +5424,6 @@ Some important flag interactions:
- A module with ``Objective-C Garbage Collection`` set to 0 cannot be
merged with a module with ``Objective-C GC Only`` set to 6.
-Automatic Linker Flags Module Flags Metadata
---------------------------------------------
-
-Some targets support embedding flags to the linker inside individual object
-files. Typically this is used in conjunction with language extensions which
-allow source files to explicitly declare the libraries they depend on, and have
-these automatically be transmitted to the linker via object files.
-
-These flags are encoded in the IR using metadata in the module flags section,
-using the ``Linker Options`` key. The merge behavior for this flag is required
-to be ``AppendUnique``, and the value for the key is expected to be a metadata
-node which should be a list of other metadata nodes, each of which should be a
-list of metadata strings defining linker options.
-
-For example, the following metadata section specifies two separate sets of
-linker options, presumably to link against ``libz`` and the ``Cocoa``
-framework::
-
- !0 = !{ i32 6, !"Linker Options",
- !{
- !{ !"-lz" },
- !{ !"-framework", !"Cocoa" } } }
- !llvm.module.flags = !{ !0 }
-
-The metadata encoding as lists of lists of options, as opposed to a collapsed
-list of options, is chosen so that the IR encoding can use multiple option
-strings to specify e.g., a single library, while still having that specifier be
-preserved as an atomic element that can be recognized by a target specific
-assembly writer or object file emitter.
-
-Each individual option is required to be either a valid option for the target's
-linker, or an option that is reserved by the target specific assembly writer or
-object file emitter. No other aspect of these options is defined by the IR.
-
C type width Module Flags Metadata
----------------------------------
@@ -5422,6 +5460,37 @@ enum is the smallest type which can represent all of its values::
!0 = !{i32 1, !"short_wchar", i32 1}
!1 = !{i32 1, !"short_enum", i32 0}
+Automatic Linker Flags Named Metadata
+=====================================
+
+Some targets support embedding flags to the linker inside individual object
+files. Typically this is used in conjunction with language extensions which
+allow source files to explicitly declare the libraries they depend on, and have
+these automatically be transmitted to the linker via object files.
+
+These flags are encoded in the IR using named metadata with the name
+``!llvm.linker.options``. Each operand is expected to be a metadata node
+which should be a list of other metadata nodes, each of which should be a
+list of metadata strings defining linker options.
+
+For example, the following metadata section specifies two separate sets of
+linker options, presumably to link against ``libz`` and the ``Cocoa``
+framework::
+
+ !0 = !{ !"-lz" },
+ !1 = !{ !"-framework", !"Cocoa" } } }
+ !llvm.linker.options = !{ !0, !1 }
+
+The metadata encoding as lists of lists of options, as opposed to a collapsed
+list of options, is chosen so that the IR encoding can use multiple option
+strings to specify e.g., a single library, while still having that specifier be
+preserved as an atomic element that can be recognized by a target specific
+assembly writer or object file emitter.
+
+Each individual option is required to be either a valid option for the target's
+linker, or an option that is reserved by the target specific assembly writer or
+object file emitter. No other aspect of these options is defined by the IR.
+
.. _intrinsicglobalvariables:
Intrinsic Global Variables
@@ -13999,62 +14068,66 @@ Element Wise Atomic Memory Intrinsics
These intrinsics are similar to the standard library memory intrinsics except
that they perform memory transfer as a sequence of atomic memory accesses.
-.. _int_memcpy_element_atomic:
+.. _int_memcpy_element_unordered_atomic:
-'``llvm.memcpy.element.atomic``' Intrinsic
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+'``llvm.memcpy.element.unordered.atomic``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
-This is an overloaded intrinsic. You can use ``llvm.memcpy.element.atomic`` on
+This is an overloaded intrinsic. You can use ``llvm.memcpy.element.unordered.atomic`` on
any integer bit width and for different address spaces. Not all targets
support all bit widths however.
::
- declare void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* <dest>, i8* <src>,
- i64 <num_elements>, i32 <element_size>)
+ declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* <dest>,
+ i8* <src>,
+ i32 <len>,
+ i32 <element_size>)
+ declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* <dest>,
+ i8* <src>,
+ i64 <len>,
+ i32 <element_size>)
Overview:
"""""""""
-The '``llvm.memcpy.element.atomic.*``' intrinsic performs copy of a block of
-memory from the source location to the destination location as a sequence of
-unordered atomic memory accesses where each access is a multiple of
-``element_size`` bytes wide and aligned at an element size boundary. For example
-each element is accessed atomically in source and destination buffers.
+The '``llvm.memcpy.element.unordered.atomic.*``' intrinsic is a specialization of the
+'``llvm.memcpy.*``' intrinsic. It differs in that the ``dest`` and ``src`` are treated
+as arrays with elements that are exactly ``element_size`` bytes, and the copy between
+buffers uses a sequence of :ref:`unordered atomic <ordering>` load/store operations
+that are a positive integer multiple of the ``element_size`` in size.
Arguments:
""""""""""
-The first argument is a pointer to the destination, the second is a
-pointer to the source. The third argument is an integer argument
-specifying the number of elements to copy, the fourth argument is size of
-the single element in bytes.
+The first three arguments are the same as they are in the :ref:`@llvm.memcpy <int_memcpy>`
+intrinsic, with the added constraint that ``len`` is required to be a positive integer
+multiple of the ``element_size``. If ``len`` is not a positive integer multiple of
+``element_size``, then the behaviour of the intrinsic is undefined.
-``element_size`` should be a power of two, greater than zero and less than
-a target-specific atomic access size limit.
+``element_size`` must be a compile-time constant positive power of two no greater than
+target-specific atomic access size limit.
-For each of the input pointers ``align`` parameter attribute must be specified.
-It must be a power of two and greater than or equal to the ``element_size``.
-Caller guarantees that both the source and destination pointers are aligned to
-that boundary.
+For each of the input pointers ``align`` parameter attribute must be specified. It
+must be a power of two no less than the ``element_size``. Caller guarantees that
+both the source and destination pointers are aligned to that boundary.
Semantics:
""""""""""
-The '``llvm.memcpy.element.atomic.*``' intrinsic copies
-'``num_elements`` * ``element_size``' bytes of memory from the source location to
-the destination location. These locations are not allowed to overlap. Memory copy
-is performed as a sequence of unordered atomic memory accesses where each access
-is guaranteed to be a multiple of ``element_size`` bytes wide and aligned at an
-element size boundary.
+The '``llvm.memcpy.element.unordered.atomic.*``' intrinsic copies ``len`` bytes of
+memory from the source location to the destination location. These locations are not
+allowed to overlap. The memory copy is performed as a sequence of load/store operations
+where each access is guaranteed to be a multiple of ``element_size`` bytes wide and
+aligned at an ``element_size`` boundary.
The order of the copy is unspecified. The same value may be read from the source
buffer many times, but only one write is issued to the destination buffer per
-element. It is well defined to have concurrent reads and writes to both source
-and destination provided those reads and writes are at least unordered atomic.
+element. It is well defined to have concurrent reads and writes to both source and
+destination provided those reads and writes are unordered atomic when specified.
This intrinsic does not provide any additional ordering guarantees over those
provided by a set of unordered loads from the source location and stores to the
@@ -14063,8 +14136,8 @@ destination.
Lowering:
"""""""""
-In the most general case call to the '``llvm.memcpy.element.atomic.*``' is lowered
-to a call to the symbol ``__llvm_memcpy_element_atomic_*``. Where '*' is replaced
-with an actual element size.
+In the most general case call to the '``llvm.memcpy.element.unordered.atomic.*``' is
+lowered to a call to the symbol ``__llvm_memcpy_element_unordered_atomic_*``. Where '*'
+is replaced with an actual element size.
-Optimizer is allowed to inline memory copy when it's profitable to do so.
+The optimizer is allowed to inline the memory copy when it's profitable to do so.
diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst
index ebc3fb772e81..ce7ed318fe4b 100644
--- a/docs/Lexicon.rst
+++ b/docs/Lexicon.rst
@@ -109,6 +109,13 @@ G
Garbage Collection. The practice of using reachability analysis instead of
explicit memory management to reclaim unused memory.
+**GVN**
+ Global Value Numbering. GVN is a pass that partitions values computed by a
+ function into congruence classes. Values ending up in the same congruence
+ class are guaranteed to be the same for every execution of the program.
+ In that respect, congruency is a compile-time approximation of equivalence
+ of values at runtime.
+
H
-
diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst
index 8d1984b65cd9..cc8484cc1e3e 100644
--- a/docs/Phabricator.rst
+++ b/docs/Phabricator.rst
@@ -54,7 +54,8 @@ reviewer understand your code.
To get a full diff, use one of the following commands (or just use Arcanist
to upload your patch):
-* ``git diff -U999999 other-branch``
+* ``git show HEAD -U999999 > mypatch.patch``
+* ``git format-patch -U999999 @{u}``
* ``svn diff --diff-cmd=diff -x -U999999``
To upload a new patch:
diff --git a/include/llvm/ADT/AllocatorList.h b/include/llvm/ADT/AllocatorList.h
index 05a549f96ec7..178c6742a87b 100644
--- a/include/llvm/ADT/AllocatorList.h
+++ b/include/llvm/ADT/AllocatorList.h
@@ -10,10 +10,16 @@
#ifndef LLVM_ADT_ALLOCATORLIST_H
#define LLVM_ADT_ALLOCATORLIST_H
+#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/simple_ilist.h"
#include "llvm/Support/Allocator.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
#include <type_traits>
+#include <utility>
namespace llvm {
@@ -39,7 +45,8 @@ template <class T, class AllocatorT> class AllocatorList : AllocatorT {
T V;
};
- typedef simple_ilist<Node> list_type;
+ using list_type = simple_ilist<Node>;
+
list_type List;
AllocatorT &getAlloc() { return *this; }
@@ -51,13 +58,17 @@ template <class T, class AllocatorT> class AllocatorList : AllocatorT {
struct Cloner {
AllocatorList &AL;
+
Cloner(AllocatorList &AL) : AL(AL) {}
+
Node *operator()(const Node &N) const { return AL.create(N.V); }
};
struct Disposer {
AllocatorList &AL;
+
Disposer(AllocatorList &AL) : AL(AL) {}
+
void operator()(Node *N) const {
N->~Node();
AL.getAlloc().Deallocate(N);
@@ -65,13 +76,13 @@ template <class T, class AllocatorT> class AllocatorList : AllocatorT {
};
public:
- typedef T value_type;
- typedef T *pointer;
- typedef T &reference;
- typedef const T *const_pointer;
- typedef const T &const_reference;
- typedef typename list_type::size_type size_type;
- typedef typename list_type::difference_type difference_type;
+ using value_type = T;
+ using pointer = T *;
+ using reference = T &;
+ using const_pointer = const T *;
+ using const_reference = const T &;
+ using size_type = typename list_type::size_type;
+ using difference_type = typename list_type::difference_type;
private:
template <class ValueT, class IteratorBase>
@@ -83,20 +94,18 @@ private:
friend class IteratorImpl;
friend AllocatorList;
- typedef iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>,
- IteratorBase, std::bidirectional_iterator_tag,
- ValueT>
- base_type;
+ using base_type =
+ iterator_adaptor_base<IteratorImpl<ValueT, IteratorBase>, IteratorBase,
+ std::bidirectional_iterator_tag, ValueT>;
public:
- typedef ValueT value_type;
- typedef ValueT *pointer;
- typedef ValueT &reference;
+ using value_type = ValueT;
+ using pointer = ValueT *;
+ using reference = ValueT &;
IteratorImpl() = default;
IteratorImpl(const IteratorImpl &) = default;
IteratorImpl &operator=(const IteratorImpl &) = default;
- ~IteratorImpl() = default;
explicit IteratorImpl(const IteratorBase &I) : base_type(I) {}
@@ -106,6 +115,8 @@ private:
OtherIteratorBase, IteratorBase>::value>::type * = nullptr)
: base_type(X.wrapped()) {}
+ ~IteratorImpl() = default;
+
reference operator*() const { return base_type::wrapped()->V; }
pointer operator->() const { return &operator*(); }
@@ -118,30 +129,34 @@ private:
};
public:
- typedef IteratorImpl<T, typename list_type::iterator> iterator;
- typedef IteratorImpl<T, typename list_type::reverse_iterator>
- reverse_iterator;
- typedef IteratorImpl<const T, typename list_type::const_iterator>
- const_iterator;
- typedef IteratorImpl<const T, typename list_type::const_reverse_iterator>
- const_reverse_iterator;
+ using iterator = IteratorImpl<T, typename list_type::iterator>;
+ using reverse_iterator =
+ IteratorImpl<T, typename list_type::reverse_iterator>;
+ using const_iterator =
+ IteratorImpl<const T, typename list_type::const_iterator>;
+ using const_reverse_iterator =
+ IteratorImpl<const T, typename list_type::const_reverse_iterator>;
AllocatorList() = default;
AllocatorList(AllocatorList &&X)
: AllocatorT(std::move(X.getAlloc())), List(std::move(X.List)) {}
+
AllocatorList(const AllocatorList &X) {
List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
}
+
AllocatorList &operator=(AllocatorList &&X) {
clear(); // Dispose of current nodes explicitly.
List = std::move(X.List);
getAlloc() = std::move(X.getAlloc());
return *this;
}
+
AllocatorList &operator=(const AllocatorList &X) {
List.cloneFrom(X.List, Cloner(*this), Disposer(*this));
return *this;
}
+
~AllocatorList() { clear(); }
void swap(AllocatorList &RHS) {
diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h
index 6b35d0aec8b2..925ebafc3fed 100644
--- a/include/llvm/ADT/ArrayRef.h
+++ b/include/llvm/ADT/ArrayRef.h
@@ -1,4 +1,4 @@
-//===--- ArrayRef.h - Array Reference Wrapper -------------------*- C++ -*-===//
+//===- ArrayRef.h - Array Reference Wrapper ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,12 +12,21 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/None.h"
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
+#include <algorithm>
#include <array>
+#include <cassert>
+#include <cstddef>
+#include <initializer_list>
+#include <iterator>
+#include <memory>
+#include <type_traits>
#include <vector>
namespace llvm {
+
/// ArrayRef - Represent a constant reference to an array (0 or more elements
/// consecutively in memory), i.e. a start pointer and a length. It allows
/// various APIs to take consecutive elements easily and conveniently.
@@ -32,28 +41,27 @@ namespace llvm {
template<typename T>
class LLVM_NODISCARD ArrayRef {
public:
- typedef const T *iterator;
- typedef const T *const_iterator;
- typedef size_t size_type;
-
- typedef std::reverse_iterator<iterator> reverse_iterator;
+ using iterator = const T *;
+ using const_iterator = const T *;
+ using size_type = size_t;
+ using reverse_iterator = std::reverse_iterator<iterator>;
private:
/// The start of the array, in an external buffer.
- const T *Data;
+ const T *Data = nullptr;
/// The number of elements.
- size_type Length;
+ size_type Length = 0;
public:
/// @name Constructors
/// @{
/// Construct an empty ArrayRef.
- /*implicit*/ ArrayRef() : Data(nullptr), Length(0) {}
+ /*implicit*/ ArrayRef() = default;
/// Construct an empty ArrayRef from None.
- /*implicit*/ ArrayRef(NoneType) : Data(nullptr), Length(0) {}
+ /*implicit*/ ArrayRef(NoneType) {}
/// Construct an ArrayRef from a single element.
/*implicit*/ ArrayRef(const T &OneElt)
@@ -282,9 +290,8 @@ namespace llvm {
template<typename T>
class LLVM_NODISCARD MutableArrayRef : public ArrayRef<T> {
public:
- typedef T *iterator;
-
- typedef std::reverse_iterator<iterator> reverse_iterator;
+ using iterator = T *;
+ using reverse_iterator = std::reverse_iterator<iterator>;
/// Construct an empty MutableArrayRef.
/*implicit*/ MutableArrayRef() : ArrayRef<T>() {}
@@ -416,19 +423,23 @@ namespace llvm {
/// This is a MutableArrayRef that owns its array.
template <typename T> class OwningArrayRef : public MutableArrayRef<T> {
public:
- OwningArrayRef() {}
+ OwningArrayRef() = default;
OwningArrayRef(size_t Size) : MutableArrayRef<T>(new T[Size], Size) {}
+
OwningArrayRef(ArrayRef<T> Data)
: MutableArrayRef<T>(new T[Data.size()], Data.size()) {
std::copy(Data.begin(), Data.end(), this->begin());
}
+
OwningArrayRef(OwningArrayRef &&Other) { *this = Other; }
+
OwningArrayRef &operator=(OwningArrayRef &&Other) {
delete[] this->data();
this->MutableArrayRef<T>::operator=(Other);
Other.MutableArrayRef<T>::operator=(MutableArrayRef<T>());
return *this;
}
+
~OwningArrayRef() { delete[] this->data(); }
};
@@ -517,13 +528,14 @@ namespace llvm {
// ArrayRefs can be treated like a POD type.
template <typename T> struct isPodLike;
- template <typename T> struct isPodLike<ArrayRef<T> > {
+ template <typename T> struct isPodLike<ArrayRef<T>> {
static const bool value = true;
};
template <typename T> hash_code hash_value(ArrayRef<T> S) {
return hash_combine_range(S.begin(), S.end());
}
+
} // end namespace llvm
#endif // LLVM_ADT_ARRAYREF_H
diff --git a/include/llvm/ADT/BreadthFirstIterator.h b/include/llvm/ADT/BreadthFirstIterator.h
index eaeecb6e057f..6bc63c283b09 100644
--- a/include/llvm/ADT/BreadthFirstIterator.h
+++ b/include/llvm/ADT/BreadthFirstIterator.h
@@ -25,7 +25,6 @@
#include "llvm/ADT/iterator_range.h"
#include <iterator>
#include <queue>
-#include <set>
#include <utility>
namespace llvm {
@@ -49,13 +48,13 @@ template <class GraphT,
class bf_iterator
: public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>,
public bf_iterator_storage<SetType> {
- typedef std::iterator<std::forward_iterator_tag, typename GT::NodeRef> super;
+ using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>;
- typedef typename GT::NodeRef NodeRef;
- typedef typename GT::ChildIteratorType ChildItTy;
+ using NodeRef = typename GT::NodeRef;
+ using ChildItTy = typename GT::ChildIteratorType;
// First element is the node reference, second is the next child to visit.
- typedef std::pair<NodeRef, Optional<ChildItTy>> QueueElement;
+ using QueueElement = std::pair<NodeRef, Optional<ChildItTy>>;
// Visit queue - used to maintain BFS ordering.
// Optional<> because we need markers for levels.
@@ -109,7 +108,7 @@ private:
}
public:
- typedef typename super::pointer pointer;
+ using pointer = typename super::pointer;
// Provide static begin and end methods as our public "constructors"
static bf_iterator begin(const GraphT &G) {
diff --git a/include/llvm/ADT/DAGDeltaAlgorithm.h b/include/llvm/ADT/DAGDeltaAlgorithm.h
index 5ea0fe872868..41fdd43efb8a 100644
--- a/include/llvm/ADT/DAGDeltaAlgorithm.h
+++ b/include/llvm/ADT/DAGDeltaAlgorithm.h
@@ -1,4 +1,4 @@
-//===--- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ----*- C++ -*--===//
+//===- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
@@ -40,12 +40,12 @@ class DAGDeltaAlgorithm {
virtual void anchor();
public:
- typedef unsigned change_ty;
- typedef std::pair<change_ty, change_ty> edge_ty;
+ using change_ty = unsigned;
+ using edge_ty = std::pair<change_ty, change_ty>;
// FIXME: Use a decent data structure.
- typedef std::set<change_ty> changeset_ty;
- typedef std::vector<changeset_ty> changesetlist_ty;
+ using changeset_ty = std::set<change_ty>;
+ using changesetlist_ty = std::vector<changeset_ty>;
public:
virtual ~DAGDeltaAlgorithm() = default;
diff --git a/include/llvm/ADT/DeltaAlgorithm.h b/include/llvm/ADT/DeltaAlgorithm.h
index a26f37dfdc7d..6becb2a60104 100644
--- a/include/llvm/ADT/DeltaAlgorithm.h
+++ b/include/llvm/ADT/DeltaAlgorithm.h
@@ -1,4 +1,4 @@
-//===--- DeltaAlgorithm.h - A Set Minimization Algorithm -------*- C++ -*--===//
+//===- DeltaAlgorithm.h - A Set Minimization Algorithm ---------*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
@@ -35,10 +35,10 @@ namespace llvm {
/// predicate.
class DeltaAlgorithm {
public:
- typedef unsigned change_ty;
+ using change_ty = unsigned;
// FIXME: Use a decent data structure.
- typedef std::set<change_ty> changeset_ty;
- typedef std::vector<changeset_ty> changesetlist_ty;
+ using changeset_ty = std::set<change_ty>;
+ using changesetlist_ty = std::vector<changeset_ty>;
private:
/// Cache of failed test results. Successful test results are never cached
@@ -90,4 +90,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_ADT_DELTAALGORITHM_H
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h
index fd8d3bf368a8..b311e69ec9d3 100644
--- a/include/llvm/ADT/DenseMap.h
+++ b/include/llvm/ADT/DenseMap.h
@@ -25,8 +25,8 @@
#include <cstddef>
#include <cstring>
#include <iterator>
-#include <limits>
#include <new>
+#include <type_traits>
#include <utility>
namespace llvm {
@@ -57,14 +57,15 @@ class DenseMapBase : public DebugEpochBase {
using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
public:
- typedef unsigned size_type;
- typedef KeyT key_type;
- typedef ValueT mapped_type;
- typedef BucketT value_type;
-
- typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT> iterator;
- typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>
- const_iterator;
+ using size_type = unsigned;
+ using key_type = KeyT;
+ using mapped_type = ValueT;
+ using value_type = BucketT;
+
+ using iterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT>;
+ using const_iterator =
+ DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>;
+
inline iterator begin() {
// When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this);
@@ -387,15 +388,18 @@ protected:
static unsigned getHashValue(const KeyT &Val) {
return KeyInfoT::getHashValue(Val);
}
+
template<typename LookupKeyT>
static unsigned getHashValue(const LookupKeyT &Val) {
return KeyInfoT::getHashValue(Val);
}
+
static const KeyT getEmptyKey() {
static_assert(std::is_base_of<DenseMapBase, DerivedT>::value,
"Must pass the derived type to this template!");
return KeyInfoT::getEmptyKey();
}
+
static const KeyT getTombstoneKey() {
return KeyInfoT::getTombstoneKey();
}
@@ -404,39 +408,51 @@ private:
unsigned getNumEntries() const {
return static_cast<const DerivedT *>(this)->getNumEntries();
}
+
void setNumEntries(unsigned Num) {
static_cast<DerivedT *>(this)->setNumEntries(Num);
}
+
void incrementNumEntries() {
setNumEntries(getNumEntries() + 1);
}
+
void decrementNumEntries() {
setNumEntries(getNumEntries() - 1);
}
+
unsigned getNumTombstones() const {
return static_cast<const DerivedT *>(this)->getNumTombstones();
}
+
void setNumTombstones(unsigned Num) {
static_cast<DerivedT *>(this)->setNumTombstones(Num);
}
+
void incrementNumTombstones() {
setNumTombstones(getNumTombstones() + 1);
}
+
void decrementNumTombstones() {
setNumTombstones(getNumTombstones() - 1);
}
+
const BucketT *getBuckets() const {
return static_cast<const DerivedT *>(this)->getBuckets();
}
+
BucketT *getBuckets() {
return static_cast<DerivedT *>(this)->getBuckets();
}
+
unsigned getNumBuckets() const {
return static_cast<const DerivedT *>(this)->getNumBuckets();
}
+
BucketT *getBucketsEnd() {
return getBuckets() + getNumBuckets();
}
+
const BucketT *getBucketsEnd() const {
return getBuckets() + getNumBuckets();
}
@@ -587,10 +603,11 @@ template <typename KeyT, typename ValueT,
typename BucketT = detail::DenseMapPair<KeyT, ValueT>>
class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>,
KeyT, ValueT, KeyInfoT, BucketT> {
+ friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
// Lift some types from the dependent base class into this class for
// simplicity of referring to them.
- typedef DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
- friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+ using BaseT = DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
BucketT *Buckets;
unsigned NumEntries;
@@ -705,6 +722,7 @@ private:
unsigned getNumEntries() const {
return NumEntries;
}
+
void setNumEntries(unsigned Num) {
NumEntries = Num;
}
@@ -712,6 +730,7 @@ private:
unsigned getNumTombstones() const {
return NumTombstones;
}
+
void setNumTombstones(unsigned Num) {
NumTombstones = Num;
}
@@ -743,10 +762,12 @@ class SmallDenseMap
: public DenseMapBase<
SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT,
ValueT, KeyInfoT, BucketT> {
+ friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
// Lift some types from the dependent base class into this class for
// simplicity of referring to them.
- typedef DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT> BaseT;
- friend class DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+ using BaseT = DenseMapBase<SmallDenseMap, KeyT, ValueT, KeyInfoT, BucketT>;
+
static_assert(isPowerOf2_64(InlineBuckets),
"InlineBuckets must be a power of 2.");
@@ -972,6 +993,7 @@ private:
unsigned getNumEntries() const {
return NumEntries;
}
+
void setNumEntries(unsigned Num) {
// NumEntries is hardcoded to be 31 bits wide.
assert(Num < (1U << 31) && "Cannot support more than 1<<31 entries");
@@ -981,6 +1003,7 @@ private:
unsigned getNumTombstones() const {
return NumTombstones;
}
+
void setNumTombstones(unsigned Num) {
NumTombstones = Num;
}
@@ -992,15 +1015,18 @@ private:
// 'storage.buffer' static type is 'char *'.
return reinterpret_cast<const BucketT *>(storage.buffer);
}
+
BucketT *getInlineBuckets() {
return const_cast<BucketT *>(
const_cast<const SmallDenseMap *>(this)->getInlineBuckets());
}
+
const LargeRep *getLargeRep() const {
assert(!Small);
// Note, same rule about aliasing as with getInlineBuckets.
return reinterpret_cast<const LargeRep *>(storage.buffer);
}
+
LargeRep *getLargeRep() {
return const_cast<LargeRep *>(
const_cast<const SmallDenseMap *>(this)->getLargeRep());
@@ -1009,10 +1035,12 @@ private:
const BucketT *getBuckets() const {
return Small ? getInlineBuckets() : getLargeRep()->Buckets;
}
+
BucketT *getBuckets() {
return const_cast<BucketT *>(
const_cast<const SmallDenseMap *>(this)->getBuckets());
}
+
unsigned getNumBuckets() const {
return Small ? InlineBuckets : getLargeRep()->NumBuckets;
}
@@ -1037,23 +1065,25 @@ private:
template <typename KeyT, typename ValueT, typename KeyInfoT, typename Bucket,
bool IsConst>
class DenseMapIterator : DebugEpochBase::HandleBase {
- typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true> ConstIterator;
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
friend class DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, false>;
+ using ConstIterator = DenseMapIterator<KeyT, ValueT, KeyInfoT, Bucket, true>;
+
public:
- typedef ptrdiff_t difference_type;
- typedef typename std::conditional<IsConst, const Bucket, Bucket>::type
- value_type;
- typedef value_type *pointer;
- typedef value_type &reference;
- typedef std::forward_iterator_tag iterator_category;
+ using difference_type = ptrdiff_t;
+ using value_type =
+ typename std::conditional<IsConst, const Bucket, Bucket>::type;
+ using pointer = value_type *;
+ using reference = value_type &;
+ using iterator_category = std::forward_iterator_tag;
private:
- pointer Ptr, End;
+ pointer Ptr = nullptr;
+ pointer End = nullptr;
public:
- DenseMapIterator() : Ptr(nullptr), End(nullptr) {}
+ DenseMapIterator() = default;
DenseMapIterator(pointer Pos, pointer E, const DebugEpochBase &Epoch,
bool NoAdvance = false)
diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h
index bb973ac65063..a96904c7dbbf 100644
--- a/include/llvm/ADT/DenseMapInfo.h
+++ b/include/llvm/ADT/DenseMapInfo.h
@@ -18,7 +18,10 @@
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
-#include "llvm/Support/type_traits.h"
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <utility>
namespace llvm {
@@ -38,15 +41,18 @@ struct DenseMapInfo<T*> {
Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
return reinterpret_cast<T*>(Val);
}
+
static inline T* getTombstoneKey() {
uintptr_t Val = static_cast<uintptr_t>(-2);
Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
return reinterpret_cast<T*>(Val);
}
+
static unsigned getHashValue(const T *PtrVal) {
return (unsigned((uintptr_t)PtrVal) >> 4) ^
(unsigned((uintptr_t)PtrVal) >> 9);
}
+
static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
};
@@ -55,6 +61,7 @@ template<> struct DenseMapInfo<char> {
static inline char getEmptyKey() { return ~0; }
static inline char getTombstoneKey() { return ~0 - 1; }
static unsigned getHashValue(const char& Val) { return Val * 37U; }
+
static bool isEqual(const char &LHS, const char &RHS) {
return LHS == RHS;
}
@@ -65,6 +72,7 @@ template <> struct DenseMapInfo<unsigned short> {
static inline unsigned short getEmptyKey() { return 0xFFFF; }
static inline unsigned short getTombstoneKey() { return 0xFFFF - 1; }
static unsigned getHashValue(const unsigned short &Val) { return Val * 37U; }
+
static bool isEqual(const unsigned short &LHS, const unsigned short &RHS) {
return LHS == RHS;
}
@@ -75,6 +83,7 @@ template<> struct DenseMapInfo<unsigned> {
static inline unsigned getEmptyKey() { return ~0U; }
static inline unsigned getTombstoneKey() { return ~0U - 1; }
static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
+
static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
return LHS == RHS;
}
@@ -84,9 +93,11 @@ template<> struct DenseMapInfo<unsigned> {
template<> struct DenseMapInfo<unsigned long> {
static inline unsigned long getEmptyKey() { return ~0UL; }
static inline unsigned long getTombstoneKey() { return ~0UL - 1L; }
+
static unsigned getHashValue(const unsigned long& Val) {
return (unsigned)(Val * 37UL);
}
+
static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
return LHS == RHS;
}
@@ -96,9 +107,11 @@ template<> struct DenseMapInfo<unsigned long> {
template<> struct DenseMapInfo<unsigned long long> {
static inline unsigned long long getEmptyKey() { return ~0ULL; }
static inline unsigned long long getTombstoneKey() { return ~0ULL - 1ULL; }
+
static unsigned getHashValue(const unsigned long long& Val) {
return (unsigned)(Val * 37ULL);
}
+
static bool isEqual(const unsigned long long& LHS,
const unsigned long long& RHS) {
return LHS == RHS;
@@ -118,6 +131,7 @@ template<> struct DenseMapInfo<int> {
static inline int getEmptyKey() { return 0x7fffffff; }
static inline int getTombstoneKey() { return -0x7fffffff - 1; }
static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
+
static bool isEqual(const int& LHS, const int& RHS) {
return LHS == RHS;
}
@@ -128,10 +142,13 @@ template<> struct DenseMapInfo<long> {
static inline long getEmptyKey() {
return (1UL << (sizeof(long) * 8 - 1)) - 1UL;
}
+
static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
+
static unsigned getHashValue(const long& Val) {
return (unsigned)(Val * 37UL);
}
+
static bool isEqual(const long& LHS, const long& RHS) {
return LHS == RHS;
}
@@ -141,9 +158,11 @@ template<> struct DenseMapInfo<long> {
template<> struct DenseMapInfo<long long> {
static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
+
static unsigned getHashValue(const long long& Val) {
return (unsigned)(Val * 37ULL);
}
+
static bool isEqual(const long long& LHS,
const long long& RHS) {
return LHS == RHS;
@@ -152,19 +171,21 @@ template<> struct DenseMapInfo<long long> {
// Provide DenseMapInfo for all pairs whose members have info.
template<typename T, typename U>
-struct DenseMapInfo<std::pair<T, U> > {
- typedef std::pair<T, U> Pair;
- typedef DenseMapInfo<T> FirstInfo;
- typedef DenseMapInfo<U> SecondInfo;
+struct DenseMapInfo<std::pair<T, U>> {
+ using Pair = std::pair<T, U>;
+ using FirstInfo = DenseMapInfo<T>;
+ using SecondInfo = DenseMapInfo<U>;
static inline Pair getEmptyKey() {
return std::make_pair(FirstInfo::getEmptyKey(),
SecondInfo::getEmptyKey());
}
+
static inline Pair getTombstoneKey() {
return std::make_pair(FirstInfo::getTombstoneKey(),
SecondInfo::getTombstoneKey());
}
+
static unsigned getHashValue(const Pair& PairVal) {
uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
| (uint64_t)SecondInfo::getHashValue(PairVal.second);
@@ -178,6 +199,7 @@ struct DenseMapInfo<std::pair<T, U> > {
key ^= (key >> 31);
return (unsigned)key;
}
+
static bool isEqual(const Pair &LHS, const Pair &RHS) {
return FirstInfo::isEqual(LHS.first, RHS.first) &&
SecondInfo::isEqual(LHS.second, RHS.second);
@@ -190,16 +212,19 @@ template <> struct DenseMapInfo<StringRef> {
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
0);
}
+
static inline StringRef getTombstoneKey() {
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
0);
}
+
static unsigned getHashValue(StringRef Val) {
assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
assert(Val.data() != getTombstoneKey().data() &&
"Cannot hash the tombstone key!");
return (unsigned)(hash_value(Val));
}
+
static bool isEqual(StringRef LHS, StringRef RHS) {
if (RHS.data() == getEmptyKey().data())
return LHS.data() == getEmptyKey().data();
@@ -215,16 +240,19 @@ template <typename T> struct DenseMapInfo<ArrayRef<T>> {
return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(0)),
size_t(0));
}
+
static inline ArrayRef<T> getTombstoneKey() {
return ArrayRef<T>(reinterpret_cast<const T *>(~static_cast<uintptr_t>(1)),
size_t(0));
}
+
static unsigned getHashValue(ArrayRef<T> Val) {
assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
assert(Val.data() != getTombstoneKey().data() &&
"Cannot hash the tombstone key!");
return (unsigned)(hash_value(Val));
}
+
static bool isEqual(ArrayRef<T> LHS, ArrayRef<T> RHS) {
if (RHS.data() == getEmptyKey().data())
return LHS.data() == getEmptyKey().data();
@@ -236,4 +264,4 @@ template <typename T> struct DenseMapInfo<ArrayRef<T>> {
} // end namespace llvm
-#endif
+#endif // LLVM_ADT_DENSEMAPINFO_H
diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h
index fcf304c3ecc4..7e5171c3f3a4 100644
--- a/include/llvm/ADT/DenseSet.h
+++ b/include/llvm/ADT/DenseSet.h
@@ -15,11 +15,18 @@
#define LLVM_ADT_DENSESET_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
+#include <cstddef>
#include <initializer_list>
+#include <iterator>
+#include <utility>
namespace llvm {
namespace detail {
+
struct DenseSetEmpty {};
// Use the empty base class trick so we can create a DenseMap where the buckets
@@ -48,13 +55,14 @@ class DenseSetImpl {
static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT),
"DenseMap buckets unexpectedly large!");
MapTy TheMap;
+
template <typename T>
using const_arg_type_t = typename const_pointer_or_const_ref<T>::type;
public:
- typedef ValueT key_type;
- typedef ValueT value_type;
- typedef unsigned size_type;
+ using key_type = ValueT;
+ using value_type = ValueT;
+ using size_type = unsigned;
explicit DenseSetImpl(unsigned InitialReserve = 0) : TheMap(InitialReserve) {}
@@ -100,11 +108,11 @@ public:
friend class ConstIterator;
public:
- typedef typename MapTy::iterator::difference_type difference_type;
- typedef ValueT value_type;
- typedef value_type *pointer;
- typedef value_type &reference;
- typedef std::forward_iterator_tag iterator_category;
+ using difference_type = typename MapTy::iterator::difference_type;
+ using value_type = ValueT;
+ using pointer = value_type *;
+ using reference = value_type &;
+ using iterator_category = std::forward_iterator_tag;
Iterator() = default;
Iterator(const typename MapTy::iterator &i) : I(i) {}
@@ -126,16 +134,14 @@ public:
friend class Iterator;
public:
- typedef typename MapTy::const_iterator::difference_type difference_type;
- typedef ValueT value_type;
- typedef value_type *pointer;
- typedef value_type &reference;
- typedef std::forward_iterator_tag iterator_category;
-
- ConstIterator(const Iterator &B) : I(B.I) {}
+ using difference_type = typename MapTy::const_iterator::difference_type;
+ using value_type = ValueT;
+ using pointer = value_type *;
+ using reference = value_type &;
+ using iterator_category = std::forward_iterator_tag;
ConstIterator() = default;
-
+ ConstIterator(const Iterator &B) : I(B.I) {}
ConstIterator(const typename MapTy::const_iterator &i) : I(i) {}
const ValueT &operator*() const { return I->getFirst(); }
@@ -147,8 +153,8 @@ public:
bool operator!=(const ConstIterator& X) const { return I != X.I; }
};
- typedef Iterator iterator;
- typedef ConstIterator const_iterator;
+ using iterator = Iterator;
+ using const_iterator = ConstIterator;
iterator begin() { return Iterator(TheMap.begin()); }
iterator end() { return Iterator(TheMap.end()); }
@@ -208,7 +214,7 @@ public:
}
};
-} // namespace detail
+} // end namespace detail
/// Implements a dense probed hash-table based set.
template <typename ValueT, typename ValueInfoT = DenseMapInfo<ValueT>>
@@ -246,4 +252,4 @@ public:
} // end namespace llvm
-#endif
+#endif // LLVM_ADT_DENSESET_H
diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h
index b020d48cb3f0..e964d7fa2391 100644
--- a/include/llvm/ADT/DepthFirstIterator.h
+++ b/include/llvm/ADT/DepthFirstIterator.h
@@ -68,13 +68,14 @@ public:
// cross edges in the spanning tree but is not used in the common case.
template <typename NodeRef, unsigned SmallSize=8>
struct df_iterator_default_set : public SmallPtrSet<NodeRef, SmallSize> {
- typedef SmallPtrSet<NodeRef, SmallSize> BaseSet;
- typedef typename BaseSet::iterator iterator;
- std::pair<iterator,bool> insert(NodeRef N) { return BaseSet::insert(N) ; }
+ using BaseSet = SmallPtrSet<NodeRef, SmallSize>;
+ using iterator = typename BaseSet::iterator;
+
+ std::pair<iterator,bool> insert(NodeRef N) { return BaseSet::insert(N); }
template <typename IterT>
void insert(IterT Begin, IterT End) { BaseSet::insert(Begin,End); }
- void completed(NodeRef) { }
+ void completed(NodeRef) {}
};
// Generic Depth First Iterator
@@ -85,15 +86,14 @@ template <class GraphT,
class df_iterator
: public std::iterator<std::forward_iterator_tag, typename GT::NodeRef>,
public df_iterator_storage<SetType, ExtStorage> {
- typedef std::iterator<std::forward_iterator_tag, typename GT::NodeRef> super;
-
- typedef typename GT::NodeRef NodeRef;
- typedef typename GT::ChildIteratorType ChildItTy;
+ using super = std::iterator<std::forward_iterator_tag, typename GT::NodeRef>;
+ using NodeRef = typename GT::NodeRef;
+ using ChildItTy = typename GT::ChildIteratorType;
// First element is node reference, second is the 'next child' to visit.
// The second child is initialized lazily to pick up graph changes during the
// DFS.
- typedef std::pair<NodeRef, Optional<ChildItTy>> StackElement;
+ using StackElement = std::pair<NodeRef, Optional<ChildItTy>>;
// VisitStack - Used to maintain the ordering. Top = current block
std::vector<StackElement> VisitStack;
@@ -103,12 +103,15 @@ private:
this->Visited.insert(Node);
VisitStack.push_back(StackElement(Node, None));
}
+
inline df_iterator() = default; // End is when stack is empty
+
inline df_iterator(NodeRef Node, SetType &S)
: df_iterator_storage<SetType, ExtStorage>(S) {
if (this->Visited.insert(Node).second)
VisitStack.push_back(StackElement(Node, None));
}
+
inline df_iterator(SetType &S)
: df_iterator_storage<SetType, ExtStorage>(S) {
// End is when stack is empty
@@ -142,7 +145,7 @@ private:
}
public:
- typedef typename super::pointer pointer;
+ using pointer = typename super::pointer;
// Provide static begin and end methods as our public "constructors"
static df_iterator begin(const GraphT &G) {
diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h
index 8fcac178ffc9..af293d4c1422 100644
--- a/include/llvm/ADT/EquivalenceClasses.h
+++ b/include/llvm/ADT/EquivalenceClasses.h
@@ -1,4 +1,4 @@
-//===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===//
+//===- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -69,6 +69,7 @@ class EquivalenceClasses {
/// leader is determined by a bit stolen from one of the pointers.
class ECValue {
friend class EquivalenceClasses;
+
mutable const ECValue *Leader, *Next;
ElemTy Data;
@@ -141,14 +142,14 @@ public:
//
/// iterator* - Provides a way to iterate over all values in the set.
- typedef typename std::set<ECValue>::const_iterator iterator;
+ using iterator = typename std::set<ECValue>::const_iterator;
+
iterator begin() const { return TheMapping.begin(); }
iterator end() const { return TheMapping.end(); }
bool empty() const { return TheMapping.empty(); }
/// member_* Iterate over the members of an equivalence class.
- ///
class member_iterator;
member_iterator member_begin(iterator I) const {
// Only leaders provide anything to iterate over.
@@ -204,7 +205,6 @@ public:
/// equivalence class it is in. This does the path-compression part that
/// makes union-find "union findy". This returns an end iterator if the value
/// is not in the equivalence class.
- ///
member_iterator findLeader(iterator I) const {
if (I == TheMapping.end()) return member_end();
return member_iterator(I->getLeader());
@@ -241,15 +241,17 @@ public:
class member_iterator : public std::iterator<std::forward_iterator_tag,
const ElemTy, ptrdiff_t> {
- typedef std::iterator<std::forward_iterator_tag,
- const ElemTy, ptrdiff_t> super;
- const ECValue *Node;
friend class EquivalenceClasses;
+ using super = std::iterator<std::forward_iterator_tag,
+ const ElemTy, ptrdiff_t>;
+
+ const ECValue *Node;
+
public:
- typedef size_t size_type;
- typedef typename super::pointer pointer;
- typedef typename super::reference reference;
+ using size_type = size_t;
+ using pointer = typename super::pointer;
+ using reference = typename super::reference;
explicit member_iterator() = default;
explicit member_iterator(const ECValue *N) : Node(N) {}
diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h
index dab18297dd3b..c5987a947e18 100644
--- a/include/llvm/ADT/FoldingSet.h
+++ b/include/llvm/ADT/FoldingSet.h
@@ -40,7 +40,7 @@ namespace llvm {
/// FoldingSetNode. The node class must also define a Profile method used to
/// establish the unique bits of data for the node. The Profile method is
/// passed a FoldingSetNodeID object which is used to gather the bits. Just
-/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class.
+/// call one of the Add* functions defined in the FoldingSetBase::NodeID class.
/// NOTE: That the folding set does not own the nodes and it is the
/// responsibility of the user to dispose of the nodes.
///
@@ -104,13 +104,13 @@ class FoldingSetNodeID;
class StringRef;
//===----------------------------------------------------------------------===//
-/// FoldingSetImpl - Implements the folding set functionality. The main
+/// FoldingSetBase - Implements the folding set functionality. The main
/// structure is an array of buckets. Each bucket is indexed by the hash of
/// the nodes it contains. The bucket itself points to the nodes contained
/// in the bucket via a singly linked list. The last node in the list points
/// back to the bucket to facilitate node removal.
///
-class FoldingSetImpl {
+class FoldingSetBase {
virtual void anchor(); // Out of line virtual method.
protected:
@@ -126,10 +126,10 @@ protected:
/// is greater than twice the number of buckets.
unsigned NumNodes;
- explicit FoldingSetImpl(unsigned Log2InitSize = 6);
- FoldingSetImpl(FoldingSetImpl &&Arg);
- FoldingSetImpl &operator=(FoldingSetImpl &&RHS);
- ~FoldingSetImpl();
+ explicit FoldingSetBase(unsigned Log2InitSize = 6);
+ FoldingSetBase(FoldingSetBase &&Arg);
+ FoldingSetBase &operator=(FoldingSetBase &&RHS);
+ ~FoldingSetBase();
public:
//===--------------------------------------------------------------------===//
@@ -152,33 +152,6 @@ public:
/// clear - Remove all nodes from the folding set.
void clear();
- /// RemoveNode - Remove a node from the folding set, returning true if one
- /// was removed or false if the node was not in the folding set.
- bool RemoveNode(Node *N);
-
- /// GetOrInsertNode - If there is an existing simple Node exactly
- /// equal to the specified node, return it. Otherwise, insert 'N' and return
- /// it instead.
- Node *GetOrInsertNode(Node *N);
-
- /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
- /// return it. If not, return the insertion token that will make insertion
- /// faster.
- Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
-
- /// InsertNode - Insert the specified node into the folding set, knowing that
- /// it is not already in the folding set. InsertPos must be obtained from
- /// FindNodeOrInsertPos.
- void InsertNode(Node *N, void *InsertPos);
-
- /// InsertNode - Insert the specified node into the folding set, knowing that
- /// it is not already in the folding set.
- void InsertNode(Node *N) {
- Node *Inserted = GetOrInsertNode(N);
- (void)Inserted;
- assert(Inserted == N && "Node already inserted!");
- }
-
/// size - Returns the number of nodes in the folding set.
unsigned size() const { return NumNodes; }
@@ -220,6 +193,28 @@ protected:
/// ComputeNodeHash - Instantiations of the FoldingSet template implement
/// this function to compute a hash value for the given node.
virtual unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const = 0;
+
+ // The below methods are protected to encourage subclasses to provide a more
+ // type-safe API.
+
+ /// RemoveNode - Remove a node from the folding set, returning true if one
+ /// was removed or false if the node was not in the folding set.
+ bool RemoveNode(Node *N);
+
+ /// GetOrInsertNode - If there is an existing simple Node exactly
+ /// equal to the specified node, return it. Otherwise, insert 'N' and return
+ /// it instead.
+ Node *GetOrInsertNode(Node *N);
+
+ /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
+ /// return it. If not, return the insertion token that will make insertion
+ /// faster.
+ Node *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos);
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set. InsertPos must be obtained from
+ /// FindNodeOrInsertPos.
+ void InsertNode(Node *N, void *InsertPos);
};
//===----------------------------------------------------------------------===//
@@ -293,7 +288,7 @@ public:
FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}
/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
- /// used to lookup the node in the FoldingSetImpl.
+ /// used to lookup the node in the FoldingSetBase.
unsigned ComputeHash() const;
bool operator==(FoldingSetNodeIDRef) const;
@@ -345,7 +340,7 @@ public:
inline void clear() { Bits.clear(); }
/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used
- /// to lookup the node in the FoldingSetImpl.
+ /// to lookup the node in the FoldingSetBase.
unsigned ComputeHash() const;
/// operator== - Used to compare two nodes to each other.
@@ -368,7 +363,7 @@ public:
};
// Convenience type to hide the implementation of the folding set.
-typedef FoldingSetImpl::Node FoldingSetNode;
+typedef FoldingSetBase::Node FoldingSetNode;
template<class T> class FoldingSetIterator;
template<class T> class FoldingSetBucketIterator;
@@ -408,6 +403,71 @@ DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
}
//===----------------------------------------------------------------------===//
+/// FoldingSetImpl - An implementation detail that lets us share code between
+/// FoldingSet and ContextualFoldingSet.
+template <class T> class FoldingSetImpl : public FoldingSetBase {
+protected:
+ explicit FoldingSetImpl(unsigned Log2InitSize)
+ : FoldingSetBase(Log2InitSize) {}
+
+ FoldingSetImpl(FoldingSetImpl &&Arg) = default;
+ FoldingSetImpl &operator=(FoldingSetImpl &&RHS) = default;
+ ~FoldingSetImpl() = default;
+
+public:
+ typedef FoldingSetIterator<T> iterator;
+ iterator begin() { return iterator(Buckets); }
+ iterator end() { return iterator(Buckets+NumBuckets); }
+
+ typedef FoldingSetIterator<const T> const_iterator;
+ const_iterator begin() const { return const_iterator(Buckets); }
+ const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
+
+ typedef FoldingSetBucketIterator<T> bucket_iterator;
+
+ bucket_iterator bucket_begin(unsigned hash) {
+ return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
+ }
+
+ bucket_iterator bucket_end(unsigned hash) {
+ return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
+ }
+
+ /// RemoveNode - Remove a node from the folding set, returning true if one
+ /// was removed or false if the node was not in the folding set.
+ bool RemoveNode(T *N) { return FoldingSetBase::RemoveNode(N); }
+
+ /// GetOrInsertNode - If there is an existing simple Node exactly
+ /// equal to the specified node, return it. Otherwise, insert 'N' and
+ /// return it instead.
+ T *GetOrInsertNode(T *N) {
+ return static_cast<T *>(FoldingSetBase::GetOrInsertNode(N));
+ }
+
+ /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
+ /// return it. If not, return the insertion token that will make insertion
+ /// faster.
+ T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
+ return static_cast<T *>(FoldingSetBase::FindNodeOrInsertPos(ID, InsertPos));
+ }
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set. InsertPos must be obtained from
+ /// FindNodeOrInsertPos.
+ void InsertNode(T *N, void *InsertPos) {
+ FoldingSetBase::InsertNode(N, InsertPos);
+ }
+
+ /// InsertNode - Insert the specified node into the folding set, knowing that
+ /// it is not already in the folding set.
+ void InsertNode(T *N) {
+ T *Inserted = GetOrInsertNode(N);
+ (void)Inserted;
+ assert(Inserted == N && "Node already inserted!");
+ }
+};
+
+//===----------------------------------------------------------------------===//
/// FoldingSet - This template class is used to instantiate a specialized
/// implementation of the folding set to the node class T. T must be a
/// subclass of FoldingSetNode and implement a Profile function.
@@ -416,8 +476,10 @@ DefaultContextualFoldingSetTrait<T, Ctx>::ComputeHash(T &X,
/// moved-from state is not a valid state for anything other than
/// move-assigning and destroying. This is primarily to enable movable APIs
/// that incorporate these objects.
-template <class T> class FoldingSet final : public FoldingSetImpl {
-private:
+template <class T> class FoldingSet final : public FoldingSetImpl<T> {
+ using Super = FoldingSetImpl<T>;
+ using Node = typename Super::Node;
+
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
/// way to convert nodes into a unique specifier.
void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
@@ -442,45 +504,10 @@ private:
public:
explicit FoldingSet(unsigned Log2InitSize = 6)
- : FoldingSetImpl(Log2InitSize) {}
-
- FoldingSet(FoldingSet &&Arg) : FoldingSetImpl(std::move(Arg)) {}
- FoldingSet &operator=(FoldingSet &&RHS) {
- (void)FoldingSetImpl::operator=(std::move(RHS));
- return *this;
- }
-
- typedef FoldingSetIterator<T> iterator;
- iterator begin() { return iterator(Buckets); }
- iterator end() { return iterator(Buckets+NumBuckets); }
-
- typedef FoldingSetIterator<const T> const_iterator;
- const_iterator begin() const { return const_iterator(Buckets); }
- const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
-
- typedef FoldingSetBucketIterator<T> bucket_iterator;
-
- bucket_iterator bucket_begin(unsigned hash) {
- return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
- }
-
- bucket_iterator bucket_end(unsigned hash) {
- return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
- }
+ : Super(Log2InitSize) {}
- /// GetOrInsertNode - If there is an existing simple Node exactly
- /// equal to the specified node, return it. Otherwise, insert 'N' and
- /// return it instead.
- T *GetOrInsertNode(Node *N) {
- return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
- }
-
- /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
- /// return it. If not, return the insertion token that will make insertion
- /// faster.
- T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
- return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
- }
+ FoldingSet(FoldingSet &&Arg) = default;
+ FoldingSet &operator=(FoldingSet &&RHS) = default;
};
//===----------------------------------------------------------------------===//
@@ -493,74 +520,42 @@ public:
/// function with signature
/// void Profile(FoldingSetNodeID &, Ctx);
template <class T, class Ctx>
-class ContextualFoldingSet final : public FoldingSetImpl {
+class ContextualFoldingSet final : public FoldingSetImpl<T> {
// Unfortunately, this can't derive from FoldingSet<T> because the
- // construction vtable for FoldingSet<T> requires
+ // construction of the vtable for FoldingSet<T> requires
// FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
// requires a single-argument T::Profile().
-private:
+ using Super = FoldingSetImpl<T>;
+ using Node = typename Super::Node;
+
Ctx Context;
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
/// way to convert nodes into a unique specifier.
- void GetNodeProfile(FoldingSetImpl::Node *N,
- FoldingSetNodeID &ID) const override {
+ void GetNodeProfile(Node *N, FoldingSetNodeID &ID) const override {
T *TN = static_cast<T *>(N);
ContextualFoldingSetTrait<T, Ctx>::Profile(*TN, ID, Context);
}
- bool NodeEquals(FoldingSetImpl::Node *N, const FoldingSetNodeID &ID,
- unsigned IDHash, FoldingSetNodeID &TempID) const override {
+ bool NodeEquals(Node *N, const FoldingSetNodeID &ID, unsigned IDHash,
+ FoldingSetNodeID &TempID) const override {
T *TN = static_cast<T *>(N);
return ContextualFoldingSetTrait<T, Ctx>::Equals(*TN, ID, IDHash, TempID,
Context);
}
- unsigned ComputeNodeHash(FoldingSetImpl::Node *N,
- FoldingSetNodeID &TempID) const override {
+ unsigned ComputeNodeHash(Node *N, FoldingSetNodeID &TempID) const override {
T *TN = static_cast<T *>(N);
return ContextualFoldingSetTrait<T, Ctx>::ComputeHash(*TN, TempID, Context);
}
public:
explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
- : FoldingSetImpl(Log2InitSize), Context(Context)
+ : Super(Log2InitSize), Context(Context)
{}
Ctx getContext() const { return Context; }
-
- typedef FoldingSetIterator<T> iterator;
- iterator begin() { return iterator(Buckets); }
- iterator end() { return iterator(Buckets+NumBuckets); }
-
- typedef FoldingSetIterator<const T> const_iterator;
- const_iterator begin() const { return const_iterator(Buckets); }
- const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
-
- typedef FoldingSetBucketIterator<T> bucket_iterator;
-
- bucket_iterator bucket_begin(unsigned hash) {
- return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
- }
-
- bucket_iterator bucket_end(unsigned hash) {
- return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
- }
-
- /// GetOrInsertNode - If there is an existing simple Node exactly
- /// equal to the specified node, return it. Otherwise, insert 'N'
- /// and return it instead.
- T *GetOrInsertNode(Node *N) {
- return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
- }
-
- /// FindNodeOrInsertPos - Look up the node specified by ID. If it
- /// exists, return it. If not, return the insertion token that will
- /// make insertion faster.
- T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
- return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
- }
};
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h
index 68149d9e3bf5..225d9eb847f0 100644
--- a/include/llvm/ADT/GraphTraits.h
+++ b/include/llvm/ADT/GraphTraits.h
@@ -1,4 +1,4 @@
-//===-- llvm/ADT/GraphTraits.h - Graph traits template ----------*- C++ -*-===//
+//===- llvm/ADT/GraphTraits.h - Graph traits template -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -41,7 +41,6 @@ struct GraphTraits {
// static ChildIteratorType child_end (NodeRef)
// Return iterators that point to the beginning and ending of the child
// node list for the specified node.
- //
// typedef ...iterator nodes_iterator; - dereference to a NodeRef
// static nodes_iterator nodes_begin(GraphType *G)
@@ -50,7 +49,6 @@ struct GraphTraits {
// static unsigned size (GraphType *G)
// Return total number of nodes in the graph
- //
// If anyone tries to use this class without having an appropriate
// specialization, make an error. If you get this error, it's because you
@@ -58,11 +56,9 @@ struct GraphTraits {
// graph, or you need to define it for a new graph type. Either that or
// your argument to XXX_begin(...) is unknown or needs to have the proper .h
// file #include'd.
- //
- typedef typename GraphType::UnknownGraphTypeError NodeRef;
+ using NodeRef = typename GraphType::UnknownGraphTypeError;
};
-
// Inverse - This class is used as a little marker class to tell the graph
// iterator to iterate over the graph in a graph defined "Inverse" ordering.
// Not all graphs define an inverse ordering, and if they do, it depends on
@@ -73,7 +69,7 @@ struct GraphTraits {
// for (; I != E; ++I) { ... }
//
// Which is equivalent to:
-// df_iterator<Inverse<Method*> > I = idf_begin(M), E = idf_end(M);
+// df_iterator<Inverse<Method*>> I = idf_begin(M), E = idf_end(M);
// for (; I != E; ++I) { ... }
//
template <class GraphType>
@@ -114,6 +110,7 @@ inverse_children(const typename GraphTraits<GraphType>::NodeRef &G) {
return make_range(GraphTraits<Inverse<GraphType>>::child_begin(G),
GraphTraits<Inverse<GraphType>>::child_end(G));
}
-} // End llvm namespace
-#endif
+} // end namespace llvm
+
+#endif // LLVM_ADT_GRAPHTRAITS_H
diff --git a/include/llvm/ADT/ImmutableList.h b/include/llvm/ADT/ImmutableList.h
index e5f51bafe995..60d63e09d426 100644
--- a/include/llvm/ADT/ImmutableList.h
+++ b/include/llvm/ADT/ImmutableList.h
@@ -63,8 +63,8 @@ public:
template <typename T>
class ImmutableList {
public:
- typedef T value_type;
- typedef ImmutableListFactory<T> Factory;
+ using value_type = T;
+ using Factory = ImmutableListFactory<T>;
private:
const ImmutableListImpl<T>* X;
@@ -141,8 +141,8 @@ public:
template <typename T>
class ImmutableListFactory {
- typedef ImmutableListImpl<T> ListTy;
- typedef FoldingSet<ListTy> CacheTy;
+ using ListTy = ImmutableListImpl<T>;
+ using CacheTy = FoldingSet<ListTy>;
CacheTy Cache;
uintptr_t Allocator;
diff --git a/include/llvm/ADT/ImmutableMap.h b/include/llvm/ADT/ImmutableMap.h
index f197d407ba3b..10d1e1f0139b 100644
--- a/include/llvm/ADT/ImmutableMap.h
+++ b/include/llvm/ADT/ImmutableMap.h
@@ -26,12 +26,12 @@ namespace llvm {
/// only the first element (the key) is used by isEqual and isLess.
template <typename T, typename S>
struct ImutKeyValueInfo {
- typedef const std::pair<T,S> value_type;
- typedef const value_type& value_type_ref;
- typedef const T key_type;
- typedef const T& key_type_ref;
- typedef const S data_type;
- typedef const S& data_type_ref;
+ using value_type = const std::pair<T,S>;
+ using value_type_ref = const value_type&;
+ using key_type = const T;
+ using key_type_ref = const T&;
+ using data_type = const S;
+ using data_type_ref = const S&;
static inline key_type_ref KeyOfValue(value_type_ref V) {
return V.first;
@@ -62,13 +62,13 @@ template <typename KeyT, typename ValT,
typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
class ImmutableMap {
public:
- typedef typename ValInfo::value_type value_type;
- typedef typename ValInfo::value_type_ref value_type_ref;
- typedef typename ValInfo::key_type key_type;
- typedef typename ValInfo::key_type_ref key_type_ref;
- typedef typename ValInfo::data_type data_type;
- typedef typename ValInfo::data_type_ref data_type_ref;
- typedef ImutAVLTree<ValInfo> TreeTy;
+ using value_type = typename ValInfo::value_type;
+ using value_type_ref = typename ValInfo::value_type_ref;
+ using key_type = typename ValInfo::key_type;
+ using key_type_ref = typename ValInfo::key_type_ref;
+ using data_type = typename ValInfo::data_type;
+ using data_type_ref = typename ValInfo::data_type_ref;
+ using TreeTy = ImutAVLTree<ValInfo>;
protected:
TreeTy* Root;
@@ -86,6 +86,10 @@ public:
if (Root) { Root->retain(); }
}
+ ~ImmutableMap() {
+ if (Root) { Root->release(); }
+ }
+
ImmutableMap &operator=(const ImmutableMap &X) {
if (Root != X.Root) {
if (X.Root) { X.Root->retain(); }
@@ -95,10 +99,6 @@ public:
return *this;
}
- ~ImmutableMap() {
- if (Root) { Root->release(); }
- }
-
class Factory {
typename TreeTy::Factory F;
const bool Canonicalize;
@@ -166,12 +166,14 @@ private:
template <typename Callback>
struct CBWrapper {
Callback C;
+
void operator()(value_type_ref V) { C(V.first,V.second); }
};
template <typename Callback>
struct CBWrapperRef {
Callback &C;
+
CBWrapperRef(Callback& c) : C(c) {}
void operator()(value_type_ref V) { C(V.first,V.second); }
@@ -254,14 +256,14 @@ template <typename KeyT, typename ValT,
typename ValInfo = ImutKeyValueInfo<KeyT,ValT>>
class ImmutableMapRef {
public:
- typedef typename ValInfo::value_type value_type;
- typedef typename ValInfo::value_type_ref value_type_ref;
- typedef typename ValInfo::key_type key_type;
- typedef typename ValInfo::key_type_ref key_type_ref;
- typedef typename ValInfo::data_type data_type;
- typedef typename ValInfo::data_type_ref data_type_ref;
- typedef ImutAVLTree<ValInfo> TreeTy;
- typedef typename TreeTy::Factory FactoryTy;
+ using value_type = typename ValInfo::value_type;
+ using value_type_ref = typename ValInfo::value_type_ref;
+ using key_type = typename ValInfo::key_type;
+ using key_type_ref = typename ValInfo::key_type_ref;
+ using data_type = typename ValInfo::data_type;
+ using data_type_ref = typename ValInfo::data_type_ref;
+ using TreeTy = ImutAVLTree<ValInfo>;
+ using FactoryTy = typename TreeTy::Factory;
protected:
TreeTy *Root;
@@ -292,6 +294,11 @@ public:
}
}
+ ~ImmutableMapRef() {
+ if (Root)
+ Root->release();
+ }
+
ImmutableMapRef &operator=(const ImmutableMapRef &X) {
if (Root != X.Root) {
if (X.Root)
@@ -306,11 +313,6 @@ public:
return *this;
}
- ~ImmutableMapRef() {
- if (Root)
- Root->release();
- }
-
static inline ImmutableMapRef getEmptyMap(FactoryTy *F) {
return ImmutableMapRef(0, F);
}
diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h
index 9c9bcb81f76b..9d580c5a3d41 100644
--- a/include/llvm/ADT/ImmutableSet.h
+++ b/include/llvm/ADT/ImmutableSet.h
@@ -41,18 +41,16 @@ template <typename ImutInfo> class ImutAVLTreeGenericIterator;
template <typename ImutInfo >
class ImutAVLTree {
public:
- typedef typename ImutInfo::key_type_ref key_type_ref;
- typedef typename ImutInfo::value_type value_type;
- typedef typename ImutInfo::value_type_ref value_type_ref;
+ using key_type_ref = typename ImutInfo::key_type_ref;
+ using value_type = typename ImutInfo::value_type;
+ using value_type_ref = typename ImutInfo::value_type_ref;
+ using Factory = ImutAVLFactory<ImutInfo>;
+ using iterator = ImutAVLTreeInOrderIterator<ImutInfo>;
- typedef ImutAVLFactory<ImutInfo> Factory;
friend class ImutAVLFactory<ImutInfo>;
friend class ImutIntervalAVLFactory<ImutInfo>;
-
friend class ImutAVLTreeGenericIterator<ImutInfo>;
- typedef ImutAVLTreeInOrderIterator<ImutInfo> iterator;
-
//===----------------------------------------------------===//
// Public Interface.
//===----------------------------------------------------===//
@@ -225,17 +223,17 @@ private:
Factory *factory;
ImutAVLTree *left;
ImutAVLTree *right;
- ImutAVLTree *prev;
- ImutAVLTree *next;
+ ImutAVLTree *prev = nullptr;
+ ImutAVLTree *next = nullptr;
- unsigned height : 28;
- unsigned IsMutable : 1;
- unsigned IsDigestCached : 1;
- unsigned IsCanonicalized : 1;
+ unsigned height : 28;
+ bool IsMutable : 1;
+ bool IsDigestCached : 1;
+ bool IsCanonicalized : 1;
value_type value;
- uint32_t digest;
- uint32_t refCount;
+ uint32_t digest = 0;
+ uint32_t refCount = 0;
//===----------------------------------------------------===//
// Internal methods (node manipulation; used by Factory).
@@ -246,9 +244,8 @@ private:
/// ImutAVLFactory.
ImutAVLTree(Factory *f, ImutAVLTree* l, ImutAVLTree* r, value_type_ref v,
unsigned height)
- : factory(f), left(l), right(r), prev(nullptr), next(nullptr),
- height(height), IsMutable(true), IsDigestCached(false),
- IsCanonicalized(0), value(v), digest(0), refCount(0)
+ : factory(f), left(l), right(r), height(height), IsMutable(true),
+ IsDigestCached(false), IsCanonicalized(false), value(v)
{
if (left) left->retain();
if (right) right->retain();
@@ -369,11 +366,11 @@ public:
template <typename ImutInfo >
class ImutAVLFactory {
friend class ImutAVLTree<ImutInfo>;
- typedef ImutAVLTree<ImutInfo> TreeTy;
- typedef typename TreeTy::value_type_ref value_type_ref;
- typedef typename TreeTy::key_type_ref key_type_ref;
- typedef DenseMap<unsigned, TreeTy*> CacheTy;
+ using TreeTy = ImutAVLTree<ImutInfo>;
+ using value_type_ref = typename TreeTy::value_type_ref;
+ using key_type_ref = typename TreeTy::key_type_ref;
+ using CacheTy = DenseMap<unsigned, TreeTy*>;
CacheTy Cache;
uintptr_t Allocator;
@@ -659,7 +656,7 @@ public:
enum VisitFlag { VisitedNone=0x0, VisitedLeft=0x1, VisitedRight=0x3,
Flags=0x3 };
- typedef ImutAVLTree<ImutInfo> TreeTy;
+ using TreeTy = ImutAVLTree<ImutInfo>;
ImutAVLTreeGenericIterator() = default;
ImutAVLTreeGenericIterator(const TreeTy *Root) {
@@ -764,11 +761,12 @@ template <typename ImutInfo>
class ImutAVLTreeInOrderIterator
: public std::iterator<std::bidirectional_iterator_tag,
ImutAVLTree<ImutInfo>> {
- typedef ImutAVLTreeGenericIterator<ImutInfo> InternalIteratorTy;
+ using InternalIteratorTy = ImutAVLTreeGenericIterator<ImutInfo>;
+
InternalIteratorTy InternalItr;
public:
- typedef ImutAVLTree<ImutInfo> TreeTy;
+ using TreeTy = ImutAVLTree<ImutInfo>;
ImutAVLTreeInOrderIterator(const TreeTy* Root) : InternalItr(Root) {
if (Root)
@@ -840,8 +838,8 @@ struct ImutAVLValueIterator
/// and generic handling of pointers is done below.
template <typename T>
struct ImutProfileInfo {
- typedef const T value_type;
- typedef const T& value_type_ref;
+ using value_type = const T;
+ using value_type_ref = const T&;
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
FoldingSetTrait<T>::Profile(X,ID);
@@ -851,8 +849,8 @@ struct ImutProfileInfo {
/// Profile traits for integers.
template <typename T>
struct ImutProfileInteger {
- typedef const T value_type;
- typedef const T& value_type_ref;
+ using value_type = const T;
+ using value_type_ref = const T&;
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddInteger(X);
@@ -878,8 +876,8 @@ PROFILE_INTEGER_INFO(unsigned long long)
/// Profile traits for booleans.
template <>
struct ImutProfileInfo<bool> {
- typedef const bool value_type;
- typedef const bool& value_type_ref;
+ using value_type = const bool;
+ using value_type_ref = const bool&;
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddBoolean(X);
@@ -890,8 +888,8 @@ struct ImutProfileInfo<bool> {
/// references to unique objects.
template <typename T>
struct ImutProfileInfo<T*> {
- typedef const T* value_type;
- typedef value_type value_type_ref;
+ using value_type = const T*;
+ using value_type_ref = value_type;
static void Profile(FoldingSetNodeID &ID, value_type_ref X) {
ID.AddPointer(X);
@@ -910,12 +908,12 @@ struct ImutProfileInfo<T*> {
/// std::equal_to<> and std::less<> to perform comparison of elements.
template <typename T>
struct ImutContainerInfo : public ImutProfileInfo<T> {
- typedef typename ImutProfileInfo<T>::value_type value_type;
- typedef typename ImutProfileInfo<T>::value_type_ref value_type_ref;
- typedef value_type key_type;
- typedef value_type_ref key_type_ref;
- typedef bool data_type;
- typedef bool data_type_ref;
+ using value_type = typename ImutProfileInfo<T>::value_type;
+ using value_type_ref = typename ImutProfileInfo<T>::value_type_ref;
+ using key_type = value_type;
+ using key_type_ref = value_type_ref;
+ using data_type = bool;
+ using data_type_ref = bool;
static key_type_ref KeyOfValue(value_type_ref D) { return D; }
static data_type_ref DataOfValue(value_type_ref) { return true; }
@@ -936,12 +934,12 @@ struct ImutContainerInfo : public ImutProfileInfo<T> {
/// their addresses.
template <typename T>
struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
- typedef typename ImutProfileInfo<T*>::value_type value_type;
- typedef typename ImutProfileInfo<T*>::value_type_ref value_type_ref;
- typedef value_type key_type;
- typedef value_type_ref key_type_ref;
- typedef bool data_type;
- typedef bool data_type_ref;
+ using value_type = typename ImutProfileInfo<T*>::value_type;
+ using value_type_ref = typename ImutProfileInfo<T*>::value_type_ref;
+ using key_type = value_type;
+ using key_type_ref = value_type_ref;
+ using data_type = bool;
+ using data_type_ref = bool;
static key_type_ref KeyOfValue(value_type_ref D) { return D; }
static data_type_ref DataOfValue(value_type_ref) { return true; }
@@ -960,9 +958,9 @@ struct ImutContainerInfo<T*> : public ImutProfileInfo<T*> {
template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
class ImmutableSet {
public:
- typedef typename ValInfo::value_type value_type;
- typedef typename ValInfo::value_type_ref value_type_ref;
- typedef ImutAVLTree<ValInfo> TreeTy;
+ using value_type = typename ValInfo::value_type;
+ using value_type_ref = typename ValInfo::value_type_ref;
+ using TreeTy = ImutAVLTree<ValInfo>;
private:
TreeTy *Root;
@@ -980,6 +978,10 @@ public:
if (Root) { Root->retain(); }
}
+ ~ImmutableSet() {
+ if (Root) { Root->release(); }
+ }
+
ImmutableSet &operator=(const ImmutableSet &X) {
if (Root != X.Root) {
if (X.Root) { X.Root->retain(); }
@@ -989,10 +991,6 @@ public:
return *this;
}
- ~ImmutableSet() {
- if (Root) { Root->release(); }
- }
-
class Factory {
typename TreeTy::Factory F;
const bool Canonicalize;
@@ -1084,7 +1082,7 @@ public:
// Iterators.
//===--------------------------------------------------===//
- typedef ImutAVLValueIterator<ImmutableSet> iterator;
+ using iterator = ImutAVLValueIterator<ImmutableSet>;
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
@@ -1112,10 +1110,10 @@ public:
template <typename ValT, typename ValInfo = ImutContainerInfo<ValT>>
class ImmutableSetRef {
public:
- typedef typename ValInfo::value_type value_type;
- typedef typename ValInfo::value_type_ref value_type_ref;
- typedef ImutAVLTree<ValInfo> TreeTy;
- typedef typename TreeTy::Factory FactoryTy;
+ using value_type = typename ValInfo::value_type;
+ using value_type_ref = typename ValInfo::value_type_ref;
+ using TreeTy = ImutAVLTree<ValInfo>;
+ using FactoryTy = typename TreeTy::Factory;
private:
TreeTy *Root;
@@ -1138,6 +1136,10 @@ public:
if (Root) { Root->retain(); }
}
+ ~ImmutableSetRef() {
+ if (Root) { Root->release(); }
+ }
+
ImmutableSetRef &operator=(const ImmutableSetRef &X) {
if (Root != X.Root) {
if (X.Root) { X.Root->retain(); }
@@ -1147,9 +1149,6 @@ public:
}
return *this;
}
- ~ImmutableSetRef() {
- if (Root) { Root->release(); }
- }
static ImmutableSetRef getEmptySet(FactoryTy *F) {
return ImmutableSetRef(0, F);
@@ -1196,7 +1195,7 @@ public:
// Iterators.
//===--------------------------------------------------===//
- typedef ImutAVLValueIterator<ImmutableSetRef> iterator;
+ using iterator = ImutAVLValueIterator<ImmutableSetRef>;
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h
index 5ba85c027920..2ee80d2cde63 100644
--- a/include/llvm/ADT/IndexedMap.h
+++ b/include/llvm/ADT/IndexedMap.h
@@ -20,28 +20,28 @@
#ifndef LLVM_ADT_INDEXEDMAP_H
#define LLVM_ADT_INDEXEDMAP_H
-#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include <cassert>
-#include <functional>
namespace llvm {
-template <typename T, typename ToIndexT = llvm::identity<unsigned> >
+template <typename T, typename ToIndexT = identity<unsigned>>
class IndexedMap {
- typedef typename ToIndexT::argument_type IndexT;
+ using IndexT = typename ToIndexT::argument_type;
// Prefer SmallVector with zero inline storage over std::vector. IndexedMaps
// can grow very large and SmallVector grows more efficiently as long as T
// is trivially copyable.
- typedef SmallVector<T, 0> StorageT;
+ using StorageT = SmallVector<T, 0>;
+
StorageT storage_;
T nullVal_;
ToIndexT toIndex_;
public:
- IndexedMap() : nullVal_(T()) { }
+ IndexedMap() : nullVal_(T()) {}
- explicit IndexedMap(const T& val) : nullVal_(val) { }
+ explicit IndexedMap(const T& val) : nullVal_(val) {}
typename StorageT::reference operator[](IndexT n) {
assert(toIndex_(n) < storage_.size() && "index out of bounds!");
@@ -80,6 +80,6 @@ template <typename T, typename ToIndexT = llvm::identity<unsigned> >
}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_ADT_INDEXEDMAP_H
diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h
index 430b9671bd1d..f71366811218 100644
--- a/include/llvm/ADT/IntervalMap.h
+++ b/include/llvm/ADT/IntervalMap.h
@@ -106,6 +106,7 @@
#include "llvm/Support/RecyclingAllocator.h"
#include <algorithm>
#include <cassert>
+#include <cstdint>
#include <iterator>
#include <new>
#include <utility>
@@ -186,7 +187,7 @@ struct IntervalMapHalfOpenInfo {
/// It should be considered private to the implementation.
namespace IntervalMapImpl {
-typedef std::pair<unsigned,unsigned> IdxPair;
+using IdxPair = std::pair<unsigned,unsigned>;
//===----------------------------------------------------------------------===//
//--- IntervalMapImpl::NodeBase ---//
@@ -445,7 +446,7 @@ struct NodeSizer {
LeafSize = DesiredLeafSize > MinLeafSize ? DesiredLeafSize : MinLeafSize
};
- typedef NodeBase<std::pair<KeyT, KeyT>, ValT, LeafSize> LeafBase;
+ using LeafBase = NodeBase<std::pair<KeyT, KeyT>, ValT, LeafSize>;
enum {
// Now that we have the leaf branching factor, compute the actual allocation
@@ -461,8 +462,8 @@ struct NodeSizer {
/// This typedef is very likely to be identical for all IntervalMaps with
/// reasonably sized entries, so the same allocator can be shared among
/// different kinds of maps.
- typedef RecyclingAllocator<BumpPtrAllocator, char,
- AllocBytes, CacheLineBytes> Allocator;
+ using Allocator =
+ RecyclingAllocator<BumpPtrAllocator, char, AllocBytes, CacheLineBytes>;
};
//===----------------------------------------------------------------------===//
@@ -930,12 +931,12 @@ template <typename KeyT, typename ValT,
unsigned N = IntervalMapImpl::NodeSizer<KeyT, ValT>::LeafSize,
typename Traits = IntervalMapInfo<KeyT>>
class IntervalMap {
- typedef IntervalMapImpl::NodeSizer<KeyT, ValT> Sizer;
- typedef IntervalMapImpl::LeafNode<KeyT, ValT, Sizer::LeafSize, Traits> Leaf;
- typedef IntervalMapImpl::BranchNode<KeyT, ValT, Sizer::BranchSize, Traits>
- Branch;
- typedef IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits> RootLeaf;
- typedef IntervalMapImpl::IdxPair IdxPair;
+ using Sizer = IntervalMapImpl::NodeSizer<KeyT, ValT>;
+ using Leaf = IntervalMapImpl::LeafNode<KeyT, ValT, Sizer::LeafSize, Traits>;
+ using Branch =
+ IntervalMapImpl::BranchNode<KeyT, ValT, Sizer::BranchSize, Traits>;
+ using RootLeaf = IntervalMapImpl::LeafNode<KeyT, ValT, N, Traits>;
+ using IdxPair = IntervalMapImpl::IdxPair;
// The RootLeaf capacity is given as a template parameter. We must compute the
// corresponding RootBranch capacity.
@@ -945,8 +946,8 @@ class IntervalMap {
RootBranchCap = DesiredRootBranchCap ? DesiredRootBranchCap : 1
};
- typedef IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits>
- RootBranch;
+ using RootBranch =
+ IntervalMapImpl::BranchNode<KeyT, ValT, RootBranchCap, Traits>;
// When branched, we store a global start key as well as the branch node.
struct RootBranchData {
@@ -955,10 +956,10 @@ class IntervalMap {
};
public:
- typedef typename Sizer::Allocator Allocator;
- typedef KeyT KeyType;
- typedef ValT ValueType;
- typedef Traits KeyTraits;
+ using Allocator = typename Sizer::Allocator;
+ using KeyType = KeyT;
+ using ValueType = ValT;
+ using KeyTraits = Traits;
private:
// The root data is either a RootLeaf or a RootBranchData instance.
@@ -1290,7 +1291,7 @@ protected:
friend class IntervalMap;
// The map referred to.
- IntervalMap *map;
+ IntervalMap *map = nullptr;
// We store a full path from the root to the current position.
// The path may be partially filled, but never between iterator calls.
@@ -1338,7 +1339,7 @@ protected:
public:
/// const_iterator - Create an iterator that isn't pointing anywhere.
- const_iterator() : map(nullptr) {}
+ const_iterator() = default;
/// setMap - Change the map iterated over. This call must be followed by a
/// call to goToBegin(), goToEnd(), or find()
@@ -1509,7 +1510,8 @@ const_iterator::treeAdvanceTo(KeyT x) {
template <typename KeyT, typename ValT, unsigned N, typename Traits>
class IntervalMap<KeyT, ValT, N, Traits>::iterator : public const_iterator {
friend class IntervalMap;
- typedef IntervalMapImpl::IdxPair IdxPair;
+
+ using IdxPair = IntervalMapImpl::IdxPair;
explicit iterator(IntervalMap &map) : const_iterator(map) {}
@@ -2003,7 +2005,7 @@ iterator::overflow(unsigned Level) {
// Elements have been rearranged, now update node sizes and stops.
bool SplitRoot = false;
unsigned Pos = 0;
- for (;;) {
+ while (true) {
KeyT Stop = Node[Pos]->stop(NewSize[Pos]-1);
if (NewNode && Pos == NewNode) {
SplitRoot = insertNode(Level, NodeRef(Node[Pos], NewSize[Pos]), Stop);
@@ -2045,8 +2047,9 @@ iterator::overflow(unsigned Level) {
///
template <typename MapA, typename MapB>
class IntervalMapOverlaps {
- typedef typename MapA::KeyType KeyType;
- typedef typename MapA::KeyTraits Traits;
+ using KeyType = typename MapA::KeyType;
+ using Traits = typename MapA::KeyTraits;
+
typename MapA::const_iterator posA;
typename MapB::const_iterator posB;
@@ -2071,7 +2074,7 @@ class IntervalMapOverlaps {
// Already overlapping.
return;
- for (;;) {
+ while (true) {
// Make a.end > b.start.
posA.advanceTo(posB.start());
if (!posA.valid() || !Traits::stopLess(posB.stop(), posA.start()))
diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h
index a77cf04ea4d1..430ef86afbd9 100644
--- a/include/llvm/ADT/IntrusiveRefCntPtr.h
+++ b/include/llvm/ADT/IntrusiveRefCntPtr.h
@@ -1,4 +1,4 @@
-//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==//
+//==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -73,9 +73,10 @@ template <class Derived> class RefCountedBase {
public:
RefCountedBase() = default;
- RefCountedBase(const RefCountedBase &) : RefCount(0) {}
+ RefCountedBase(const RefCountedBase &) {}
void Retain() const { ++RefCount; }
+
void Release() const {
assert(RefCount > 0 && "Reference count is already zero.");
if (--RefCount == 0)
@@ -136,7 +137,7 @@ template <typename T> class IntrusiveRefCntPtr {
T *Obj = nullptr;
public:
- typedef T element_type;
+ using element_type = T;
explicit IntrusiveRefCntPtr() = default;
IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); }
@@ -153,13 +154,13 @@ public:
retain();
}
+ ~IntrusiveRefCntPtr() { release(); }
+
IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) {
swap(S);
return *this;
}
- ~IntrusiveRefCntPtr() { release(); }
-
T &operator*() const { return *Obj; }
T *operator->() const { return Obj; }
T *get() const { return Obj; }
@@ -183,6 +184,7 @@ private:
if (Obj)
IntrusiveRefCntPtrInfo<T>::retain(Obj);
}
+
void release() {
if (Obj)
IntrusiveRefCntPtrInfo<T>::release(Obj);
@@ -248,14 +250,16 @@ bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
template <typename From> struct simplify_type;
template <class T> struct simplify_type<IntrusiveRefCntPtr<T>> {
- typedef T *SimpleType;
+ using SimpleType = T *;
+
static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T> &Val) {
return Val.get();
}
};
template <class T> struct simplify_type<const IntrusiveRefCntPtr<T>> {
- typedef /*const*/ T *SimpleType;
+ using SimpleType = /*const*/ T *;
+
static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T> &Val) {
return Val.get();
}
diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h
index ac1885758cb9..26a555ee1d3b 100644
--- a/include/llvm/ADT/MapVector.h
+++ b/include/llvm/ADT/MapVector.h
@@ -19,6 +19,12 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <type_traits>
+#include <utility>
#include <vector>
namespace llvm {
@@ -27,20 +33,20 @@ namespace llvm {
/// in a deterministic order. The values are kept in a std::vector and the
/// mapping is done with DenseMap from Keys to indexes in that vector.
template<typename KeyT, typename ValueT,
- typename MapType = llvm::DenseMap<KeyT, unsigned>,
- typename VectorType = std::vector<std::pair<KeyT, ValueT> > >
+ typename MapType = DenseMap<KeyT, unsigned>,
+ typename VectorType = std::vector<std::pair<KeyT, ValueT>>>
class MapVector {
- typedef typename VectorType::value_type value_type;
- typedef typename VectorType::size_type size_type;
+ using value_type = typename VectorType::value_type;
+ using size_type = typename VectorType::size_type;
MapType Map;
VectorType Vector;
public:
- typedef typename VectorType::iterator iterator;
- typedef typename VectorType::const_iterator const_iterator;
- typedef typename VectorType::reverse_iterator reverse_iterator;
- typedef typename VectorType::const_reverse_iterator const_reverse_iterator;
+ using iterator = typename VectorType::iterator;
+ using const_iterator = typename VectorType::const_iterator;
+ using reverse_iterator = typename VectorType::reverse_iterator;
+ using const_reverse_iterator = typename VectorType::const_reverse_iterator;
/// Clear the MapVector and return the underlying vector.
VectorType takeVector() {
@@ -220,4 +226,4 @@ struct SmallMapVector
} // end namespace llvm
-#endif
+#endif // LLVM_ADT_MAPVECTOR_H
diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h
index 701872c9f63f..b782d9da17ac 100644
--- a/include/llvm/ADT/Optional.h
+++ b/include/llvm/ADT/Optional.h
@@ -1,4 +1,4 @@
-//===-- Optional.h - Simple variant for passing optional values ---*- C++ -*-=//
+//===- Optional.h - Simple variant for passing optional values --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,6 +19,8 @@
#include "llvm/ADT/None.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/type_traits.h"
+#include <algorithm>
#include <cassert>
#include <new>
#include <utility>
@@ -28,15 +30,18 @@ namespace llvm {
template<typename T>
class Optional {
AlignedCharArrayUnion<T> storage;
- bool hasVal;
+ bool hasVal = false;
+
public:
- typedef T value_type;
+ using value_type = T;
+
+ Optional(NoneType) {}
+ explicit Optional() {}
- Optional(NoneType) : hasVal(false) {}
- explicit Optional() : hasVal(false) {}
Optional(const T &y) : hasVal(true) {
new (storage.buffer) T(y);
}
+
Optional(const Optional &O) : hasVal(O.hasVal) {
if (hasVal)
new (storage.buffer) T(*O);
@@ -45,12 +50,18 @@ public:
Optional(T &&y) : hasVal(true) {
new (storage.buffer) T(std::forward<T>(y));
}
+
Optional(Optional<T> &&O) : hasVal(O) {
if (O) {
new (storage.buffer) T(std::move(*O));
O.reset();
}
}
+
+ ~Optional() {
+ reset();
+ }
+
Optional &operator=(T &&y) {
if (hasVal)
**this = std::move(y);
@@ -60,6 +71,7 @@ public:
}
return *this;
}
+
Optional &operator=(Optional &&O) {
if (!O)
reset();
@@ -112,10 +124,6 @@ public:
}
}
- ~Optional() {
- reset();
- }
-
const T* getPointer() const { assert(hasVal); return reinterpret_cast<const T*>(storage.buffer); }
T* getPointer() { assert(hasVal); return reinterpret_cast<T*>(storage.buffer); }
const T& getValue() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); }
@@ -144,8 +152,7 @@ public:
#endif
};
-template <typename T> struct isPodLike;
-template <typename T> struct isPodLike<Optional<T> > {
+template <typename T> struct isPodLike<Optional<T>> {
// An Optional<T> is pod-like if T is.
static const bool value = isPodLike<T>::value;
};
@@ -284,6 +291,6 @@ template <typename T> bool operator>=(const T &X, const Optional<T> &Y) {
return !(X < Y);
}
-} // end llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_ADT_OPTIONAL_H
diff --git a/include/llvm/ADT/PackedVector.h b/include/llvm/ADT/PackedVector.h
index 8f925f1ff5cb..95adc2926813 100644
--- a/include/llvm/ADT/PackedVector.h
+++ b/include/llvm/ADT/PackedVector.h
@@ -76,8 +76,8 @@ template <typename T, unsigned BitNum, typename BitVectorTy = BitVector>
class PackedVector : public PackedVectorBase<T, BitNum, BitVectorTy,
std::numeric_limits<T>::is_signed> {
BitVectorTy Bits;
- typedef PackedVectorBase<T, BitNum, BitVectorTy,
- std::numeric_limits<T>::is_signed> base;
+ using base = PackedVectorBase<T, BitNum, BitVectorTy,
+ std::numeric_limits<T>::is_signed>;
public:
class reference {
@@ -99,7 +99,7 @@ public:
};
PackedVector() = default;
- explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) { }
+ explicit PackedVector(unsigned size) : Bits(size << (BitNum-1)) {}
bool empty() const { return Bits.empty(); }
diff --git a/include/llvm/ADT/PointerEmbeddedInt.h b/include/llvm/ADT/PointerEmbeddedInt.h
index 2279d43405fa..34323b5b8af4 100644
--- a/include/llvm/ADT/PointerEmbeddedInt.h
+++ b/include/llvm/ADT/PointerEmbeddedInt.h
@@ -13,7 +13,10 @@
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
+#include <cassert>
#include <climits>
+#include <cstdint>
+#include <type_traits>
namespace llvm {
@@ -29,7 +32,7 @@ namespace llvm {
/// Also, the default constructed value zero initializes the integer.
template <typename IntT, int Bits = sizeof(IntT) * CHAR_BIT>
class PointerEmbeddedInt {
- uintptr_t Value;
+ uintptr_t Value = 0;
// Note: This '<' is correct; using '<=' would result in some shifts
// overflowing their storage types.
@@ -54,15 +57,12 @@ class PointerEmbeddedInt {
explicit PointerEmbeddedInt(uintptr_t Value, RawValueTag) : Value(Value) {}
public:
- PointerEmbeddedInt() : Value(0) {}
+ PointerEmbeddedInt() = default;
- PointerEmbeddedInt(IntT I) {
- *this = I;
- }
+ PointerEmbeddedInt(IntT I) { *this = I; }
PointerEmbeddedInt &operator=(IntT I) {
- assert((std::is_signed<IntT>::value ? llvm::isInt<Bits>(I)
- : llvm::isUInt<Bits>(I)) &&
+ assert((std::is_signed<IntT>::value ? isInt<Bits>(I) : isUInt<Bits>(I)) &&
"Integer has bits outside those preserved!");
Value = static_cast<uintptr_t>(I) << Shift;
return *this;
@@ -81,15 +81,17 @@ public:
// types.
template <typename IntT, int Bits>
class PointerLikeTypeTraits<PointerEmbeddedInt<IntT, Bits>> {
- typedef PointerEmbeddedInt<IntT, Bits> T;
+ using T = PointerEmbeddedInt<IntT, Bits>;
public:
static inline void *getAsVoidPointer(const T &P) {
return reinterpret_cast<void *>(P.Value);
}
+
static inline T getFromVoidPointer(void *P) {
return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
}
+
static inline T getFromVoidPointer(const void *P) {
return T(reinterpret_cast<uintptr_t>(P), typename T::RawValueTag());
}
@@ -101,17 +103,19 @@ public:
// itself can be a key.
template <typename IntT, int Bits>
struct DenseMapInfo<PointerEmbeddedInt<IntT, Bits>> {
- typedef PointerEmbeddedInt<IntT, Bits> T;
-
- typedef DenseMapInfo<IntT> IntInfo;
+ using T = PointerEmbeddedInt<IntT, Bits>;
+ using IntInfo = DenseMapInfo<IntT>;
static inline T getEmptyKey() { return IntInfo::getEmptyKey(); }
static inline T getTombstoneKey() { return IntInfo::getTombstoneKey(); }
+
static unsigned getHashValue(const T &Arg) {
return IntInfo::getHashValue(Arg);
}
+
static bool isEqual(const T &LHS, const T &RHS) { return LHS == RHS; }
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_ADT_POINTEREMBEDDEDINT_H
diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h
index 7ce70ebc8ce0..aeab641f5715 100644
--- a/include/llvm/ADT/PointerUnion.h
+++ b/include/llvm/ADT/PointerUnion.h
@@ -158,7 +158,7 @@ public:
assert(
get<PT1>() == Val.getPointer() &&
"Can't get the address because PointerLikeTypeTraits changes the ptr");
- return (PT1 *)Val.getAddrOfPointer();
+ return const_cast<PT1 *>(reinterpret_cast<const PT1 *>(Val.getAddrOfPointer()));
}
/// Assignment from nullptr which just clears the union.
diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h
index d52128e294a3..22b0c1bdaf4d 100644
--- a/include/llvm/ADT/ScopedHashTable.h
+++ b/include/llvm/ADT/ScopedHashTable.h
@@ -109,6 +109,7 @@ private:
ScopedHashTableVal<K, V> *getLastValInScope() {
return LastValInScope;
}
+
void setLastValInScope(ScopedHashTableVal<K, V> *Val) {
LastValInScope = Val;
}
@@ -151,13 +152,14 @@ class ScopedHashTable {
public:
/// ScopeTy - This is a helpful typedef that allows clients to get easy access
/// to the name of the scope for this hash table.
- typedef ScopedHashTableScope<K, V, KInfo, AllocatorTy> ScopeTy;
- typedef unsigned size_type;
+ using ScopeTy = ScopedHashTableScope<K, V, KInfo, AllocatorTy>;
+ using size_type = unsigned;
private:
friend class ScopedHashTableScope<K, V, KInfo, AllocatorTy>;
- typedef ScopedHashTableVal<K, V> ValTy;
+ using ValTy = ScopedHashTableVal<K, V>;
+
DenseMap<K, ValTy*, KInfo> TopLevelMap;
ScopeTy *CurScope = nullptr;
@@ -165,7 +167,7 @@ private:
public:
ScopedHashTable() = default;
- ScopedHashTable(AllocatorTy A) : CurScope(0), Allocator(A) {}
+ ScopedHashTable(AllocatorTy A) : Allocator(A) {}
ScopedHashTable(const ScopedHashTable &) = delete;
ScopedHashTable &operator=(const ScopedHashTable &) = delete;
@@ -194,7 +196,7 @@ public:
insertIntoScope(CurScope, Key, Val);
}
- typedef ScopedHashTableIterator<K, V, KInfo> iterator;
+ using iterator = ScopedHashTableIterator<K, V, KInfo>;
iterator end() { return iterator(0); }
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
index 0ff427066959..b6391746639b 100644
--- a/include/llvm/ADT/SmallBitVector.h
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -15,8 +15,15 @@
#define LLVM_ADT_SMALLBITVECTOR_H
#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/MathExtras.h"
+#include <algorithm>
#include <cassert>
+#include <climits>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <utility>
namespace llvm {
@@ -29,7 +36,7 @@ class SmallBitVector {
// TODO: In "large" mode, a pointer to a BitVector is used, leading to an
// unnecessary level of indirection. It would be more efficient to use a
// pointer to memory containing size, allocation size, and the array of bits.
- uintptr_t X;
+ uintptr_t X = 1;
enum {
// The number of bits in this class.
@@ -54,7 +61,8 @@ class SmallBitVector {
"Unsupported word size");
public:
- typedef unsigned size_type;
+ using size_type = unsigned;
+
// Encapsulation of a single bit.
class reference {
SmallBitVector &TheVector;
@@ -134,21 +142,8 @@ private:
}
public:
- typedef const_set_bits_iterator_impl<SmallBitVector> const_set_bits_iterator;
- typedef const_set_bits_iterator set_iterator;
-
- const_set_bits_iterator set_bits_begin() const {
- return const_set_bits_iterator(*this);
- }
- const_set_bits_iterator set_bits_end() const {
- return const_set_bits_iterator(*this, -1);
- }
- iterator_range<const_set_bits_iterator> set_bits() const {
- return make_range(set_bits_begin(), set_bits_end());
- }
-
/// Creates an empty bitvector.
- SmallBitVector() : X(1) {}
+ SmallBitVector() = default;
/// Creates a bitvector of specified number of bits. All bits are initialized
/// to the specified value.
@@ -176,6 +171,21 @@ public:
delete getPointer();
}
+ using const_set_bits_iterator = const_set_bits_iterator_impl<SmallBitVector>;
+ using set_iterator = const_set_bits_iterator;
+
+ const_set_bits_iterator set_bits_begin() const {
+ return const_set_bits_iterator(*this);
+ }
+
+ const_set_bits_iterator set_bits_end() const {
+ return const_set_bits_iterator(*this, -1);
+ }
+
+ iterator_range<const_set_bits_iterator> set_bits() const {
+ return make_range(set_bits_begin(), set_bits_end());
+ }
+
/// Tests whether there are no bits in this bitvector.
bool empty() const {
return isSmall() ? getSmallSize() == 0 : getPointer()->empty();
@@ -677,14 +687,16 @@ operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) {
return Result;
}
-} // End llvm namespace
+} // end namespace llvm
namespace std {
- /// Implement std::swap in terms of BitVector swap.
- inline void
- swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) {
- LHS.swap(RHS);
- }
+
+/// Implement std::swap in terms of BitVector swap.
+inline void
+swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) {
+ LHS.swap(RHS);
}
-#endif
+} // end namespace std
+
+#endif // LLVM_ADT_SMALLBITVECTOR_H
diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h
index 6dac1677b7a2..d52d0f07f9a6 100644
--- a/include/llvm/ADT/SmallSet.h
+++ b/include/llvm/ADT/SmallSet.h
@@ -39,8 +39,9 @@ class SmallSet {
/// we will never use.
SmallVector<T, N> Vector;
std::set<T, C> Set;
- typedef typename SmallVector<T, N>::const_iterator VIterator;
- typedef typename SmallVector<T, N>::iterator mutable_iterator;
+
+ using VIterator = typename SmallVector<T, N>::const_iterator;
+ using mutable_iterator = typename SmallVector<T, N>::iterator;
// In small mode SmallPtrSet uses linear search for the elements, so it is
// not a good idea to choose this value too high. You may consider using a
@@ -48,7 +49,7 @@ class SmallSet {
static_assert(N <= 32, "N should be small");
public:
- typedef size_t size_type;
+ using size_type = size_t;
SmallSet() = default;
diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h
index bbea8619a673..ffcf998a3d32 100644
--- a/include/llvm/ADT/StringExtras.h
+++ b/include/llvm/ADT/StringExtras.h
@@ -14,6 +14,7 @@
#ifndef LLVM_ADT_STRINGEXTRAS_H
#define LLVM_ADT_STRINGEXTRAS_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <cstddef>
@@ -40,6 +41,11 @@ static inline StringRef toStringRef(bool B) {
return StringRef(B ? "true" : "false");
}
+/// Construct a string ref from an array ref of unsigned chars.
+static inline StringRef toStringRef(ArrayRef<uint8_t> Input) {
+ return StringRef(reinterpret_cast<const char *>(Input.begin()), Input.size());
+}
+
/// Interpret the given character \p C as a hexadecimal digit and return its
/// value.
///
@@ -68,7 +74,7 @@ static inline std::string utohexstr(uint64_t X, bool LowerCase = false) {
/// Convert buffer \p Input to its hexadecimal representation.
/// The returned string is double the size of \p Input.
-static inline std::string toHex(StringRef Input) {
+inline std::string toHex(StringRef Input) {
static const char *const LUT = "0123456789ABCDEF";
size_t Length = Input.size();
@@ -82,6 +88,10 @@ static inline std::string toHex(StringRef Input) {
return Output;
}
+inline std::string toHex(ArrayRef<uint8_t> Input) {
+ return toHex(toStringRef(Input));
+}
+
static inline uint8_t hexFromNibbles(char MSB, char LSB) {
unsigned U1 = hexDigitValue(MSB);
unsigned U2 = hexDigitValue(LSB);
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index 07626982d289..26a991812a3a 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -239,7 +239,9 @@ public:
/// Default constructor is the same as an empty string and leaves all
/// triple fields unknown.
- Triple() : Data(), Arch(), Vendor(), OS(), Environment(), ObjectFormat() {}
+ Triple()
+ : Data(), Arch(), SubArch(), Vendor(), OS(), Environment(),
+ ObjectFormat() {}
explicit Triple(const Twine &Str);
Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr);
diff --git a/include/llvm/ADT/ilist_base.h b/include/llvm/ADT/ilist_base.h
index 1ffc864bea2f..3d818a48d41d 100644
--- a/include/llvm/ADT/ilist_base.h
+++ b/include/llvm/ADT/ilist_base.h
@@ -1,4 +1,4 @@
-//===- llvm/ADT/ilist_base.h - Intrusive List Base ---------------*- C++ -*-==//
+//===- llvm/ADT/ilist_base.h - Intrusive List Base --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,15 +12,13 @@
#include "llvm/ADT/ilist_node_base.h"
#include <cassert>
-#include <cstddef>
-#include <type_traits>
namespace llvm {
/// Implementations of list algorithms using ilist_node_base.
template <bool EnableSentinelTracking> class ilist_base {
public:
- typedef ilist_node_base<EnableSentinelTracking> node_base_type;
+ using node_base_type = ilist_node_base<EnableSentinelTracking>;
static void insertBeforeImpl(node_base_type &Next, node_base_type &N) {
node_base_type &Prev = *Next.getPrev();
diff --git a/include/llvm/ADT/ilist_iterator.h b/include/llvm/ADT/ilist_iterator.h
index c848d1a134f1..671e644e0154 100644
--- a/include/llvm/ADT/ilist_iterator.h
+++ b/include/llvm/ADT/ilist_iterator.h
@@ -1,4 +1,4 @@
-//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator -------*- C++ -*-==//
+//===- llvm/ADT/ilist_iterator.h - Intrusive List Iterator ------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -23,28 +23,30 @@ namespace ilist_detail {
/// Find const-correct node types.
template <class OptionsT, bool IsConst> struct IteratorTraits;
template <class OptionsT> struct IteratorTraits<OptionsT, false> {
- typedef typename OptionsT::value_type value_type;
- typedef typename OptionsT::pointer pointer;
- typedef typename OptionsT::reference reference;
- typedef ilist_node_impl<OptionsT> *node_pointer;
- typedef ilist_node_impl<OptionsT> &node_reference;
+ using value_type = typename OptionsT::value_type;
+ using pointer = typename OptionsT::pointer;
+ using reference = typename OptionsT::reference;
+ using node_pointer = ilist_node_impl<OptionsT> *;
+ using node_reference = ilist_node_impl<OptionsT> &;
};
template <class OptionsT> struct IteratorTraits<OptionsT, true> {
- typedef const typename OptionsT::value_type value_type;
- typedef typename OptionsT::const_pointer pointer;
- typedef typename OptionsT::const_reference reference;
- typedef const ilist_node_impl<OptionsT> *node_pointer;
- typedef const ilist_node_impl<OptionsT> &node_reference;
+ using value_type = const typename OptionsT::value_type;
+ using pointer = typename OptionsT::const_pointer;
+ using reference = typename OptionsT::const_reference;
+ using node_pointer = const ilist_node_impl<OptionsT> *;
+ using node_reference = const ilist_node_impl<OptionsT> &;
};
template <bool IsReverse> struct IteratorHelper;
template <> struct IteratorHelper<false> : ilist_detail::NodeAccess {
- typedef ilist_detail::NodeAccess Access;
+ using Access = ilist_detail::NodeAccess;
+
template <class T> static void increment(T *&I) { I = Access::getNext(*I); }
template <class T> static void decrement(T *&I) { I = Access::getPrev(*I); }
};
template <> struct IteratorHelper<true> : ilist_detail::NodeAccess {
- typedef ilist_detail::NodeAccess Access;
+ using Access = ilist_detail::NodeAccess;
+
template <class T> static void increment(T *&I) { I = Access::getPrev(*I); }
template <class T> static void decrement(T *&I) { I = Access::getNext(*I); }
};
@@ -58,24 +60,23 @@ class ilist_iterator : ilist_detail::SpecificNodeAccess<OptionsT> {
friend ilist_iterator<OptionsT, !IsReverse, IsConst>;
friend ilist_iterator<OptionsT, !IsReverse, !IsConst>;
- typedef ilist_detail::IteratorTraits<OptionsT, IsConst> Traits;
- typedef ilist_detail::SpecificNodeAccess<OptionsT> Access;
+ using Traits = ilist_detail::IteratorTraits<OptionsT, IsConst>;
+ using Access = ilist_detail::SpecificNodeAccess<OptionsT>;
public:
- typedef typename Traits::value_type value_type;
- typedef typename Traits::pointer pointer;
- typedef typename Traits::reference reference;
- typedef ptrdiff_t difference_type;
- typedef std::bidirectional_iterator_tag iterator_category;
-
- typedef typename OptionsT::const_pointer const_pointer;
- typedef typename OptionsT::const_reference const_reference;
+ using value_type = typename Traits::value_type;
+ using pointer = typename Traits::pointer;
+ using reference = typename Traits::reference;
+ using difference_type = ptrdiff_t;
+ using iterator_category = std::bidirectional_iterator_tag;
+ using const_pointer = typename OptionsT::const_pointer;
+ using const_reference = typename OptionsT::const_reference;
private:
- typedef typename Traits::node_pointer node_pointer;
- typedef typename Traits::node_reference node_reference;
+ using node_pointer = typename Traits::node_pointer;
+ using node_reference = typename Traits::node_reference;
- node_pointer NodePtr;
+ node_pointer NodePtr = nullptr;
public:
/// Create from an ilist_node.
@@ -83,7 +84,7 @@ public:
explicit ilist_iterator(pointer NP) : NodePtr(Access::getNodePtr(NP)) {}
explicit ilist_iterator(reference NR) : NodePtr(Access::getNodePtr(&NR)) {}
- ilist_iterator() : NodePtr(nullptr) {}
+ ilist_iterator() = default;
// This is templated so that we can allow constructing a const iterator from
// a nonconst iterator...
@@ -184,8 +185,8 @@ template <typename From> struct simplify_type;
/// FIXME: remove this, since there is no implicit conversion to NodeTy.
template <class OptionsT, bool IsConst>
struct simplify_type<ilist_iterator<OptionsT, false, IsConst>> {
- typedef ilist_iterator<OptionsT, false, IsConst> iterator;
- typedef typename iterator::pointer SimpleType;
+ using iterator = ilist_iterator<OptionsT, false, IsConst>;
+ using SimpleType = typename iterator::pointer;
static SimpleType getSimplifiedValue(const iterator &Node) { return &*Node; }
};
diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h
index 7244d0f40586..3362611697cb 100644
--- a/include/llvm/ADT/ilist_node.h
+++ b/include/llvm/ADT/ilist_node.h
@@ -1,4 +1,4 @@
-//==-- llvm/ADT/ilist_node.h - Intrusive Linked List Helper ------*- C++ -*-==//
+//===- llvm/ADT/ilist_node.h - Intrusive Linked List Helper -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,11 +21,10 @@
namespace llvm {
namespace ilist_detail {
+
struct NodeAccess;
-} // end namespace ilist_detail
-template<typename NodeTy>
-struct ilist_traits;
+} // end namespace ilist_detail
template <class OptionsT, bool IsReverse, bool IsConst> class ilist_iterator;
template <class OptionsT> class ilist_sentinel;
@@ -39,9 +38,9 @@ template <class OptionsT> class ilist_sentinel;
/// provide type safety: you can't insert nodes of \a ilist_node_impl into the
/// wrong \a simple_ilist or \a iplist.
template <class OptionsT> class ilist_node_impl : OptionsT::node_base_type {
- typedef typename OptionsT::value_type value_type;
- typedef typename OptionsT::node_base_type node_base_type;
- typedef typename OptionsT::list_base_type list_base_type;
+ using value_type = typename OptionsT::value_type;
+ using node_base_type = typename OptionsT::node_base_type;
+ using list_base_type = typename OptionsT::list_base_type;
friend typename OptionsT::list_base_type;
friend struct ilist_detail::NodeAccess;
@@ -52,17 +51,18 @@ template <class OptionsT> class ilist_node_impl : OptionsT::node_base_type {
friend class ilist_iterator<OptionsT, true, true>;
protected:
- ilist_node_impl() = default;
+ using self_iterator = ilist_iterator<OptionsT, false, false>;
+ using const_self_iterator = ilist_iterator<OptionsT, false, true>;
+ using reverse_self_iterator = ilist_iterator<OptionsT, true, false>;
+ using const_reverse_self_iterator = ilist_iterator<OptionsT, true, true>;
- typedef ilist_iterator<OptionsT, false, false> self_iterator;
- typedef ilist_iterator<OptionsT, false, true> const_self_iterator;
- typedef ilist_iterator<OptionsT, true, false> reverse_self_iterator;
- typedef ilist_iterator<OptionsT, true, true> const_reverse_self_iterator;
+ ilist_node_impl() = default;
private:
ilist_node_impl *getPrev() {
return static_cast<ilist_node_impl *>(node_base_type::getPrev());
}
+
ilist_node_impl *getNext() {
return static_cast<ilist_node_impl *>(node_base_type::getNext());
}
@@ -70,6 +70,7 @@ private:
const ilist_node_impl *getPrev() const {
return static_cast<ilist_node_impl *>(node_base_type::getPrev());
}
+
const ilist_node_impl *getNext() const {
return static_cast<ilist_node_impl *>(node_base_type::getNext());
}
@@ -80,9 +81,11 @@ private:
public:
self_iterator getIterator() { return self_iterator(*this); }
const_self_iterator getIterator() const { return const_self_iterator(*this); }
+
reverse_self_iterator getReverseIterator() {
return reverse_self_iterator(*this);
}
+
const_reverse_self_iterator getReverseIterator() const {
return const_reverse_self_iterator(*this);
}
@@ -151,6 +154,7 @@ class ilist_node
};
namespace ilist_detail {
+
/// An access class for ilist_node private API.
///
/// This gives access to the private parts of ilist nodes. Nodes for an ilist
@@ -163,15 +167,18 @@ protected:
static ilist_node_impl<OptionsT> *getNodePtr(typename OptionsT::pointer N) {
return N;
}
+
template <class OptionsT>
static const ilist_node_impl<OptionsT> *
getNodePtr(typename OptionsT::const_pointer N) {
return N;
}
+
template <class OptionsT>
static typename OptionsT::pointer getValuePtr(ilist_node_impl<OptionsT> *N) {
return static_cast<typename OptionsT::pointer>(N);
}
+
template <class OptionsT>
static typename OptionsT::const_pointer
getValuePtr(const ilist_node_impl<OptionsT> *N) {
@@ -182,15 +189,18 @@ protected:
static ilist_node_impl<OptionsT> *getPrev(ilist_node_impl<OptionsT> &N) {
return N.getPrev();
}
+
template <class OptionsT>
static ilist_node_impl<OptionsT> *getNext(ilist_node_impl<OptionsT> &N) {
return N.getNext();
}
+
template <class OptionsT>
static const ilist_node_impl<OptionsT> *
getPrev(const ilist_node_impl<OptionsT> &N) {
return N.getPrev();
}
+
template <class OptionsT>
static const ilist_node_impl<OptionsT> *
getNext(const ilist_node_impl<OptionsT> &N) {
@@ -200,23 +210,27 @@ protected:
template <class OptionsT> struct SpecificNodeAccess : NodeAccess {
protected:
- typedef typename OptionsT::pointer pointer;
- typedef typename OptionsT::const_pointer const_pointer;
- typedef ilist_node_impl<OptionsT> node_type;
+ using pointer = typename OptionsT::pointer;
+ using const_pointer = typename OptionsT::const_pointer;
+ using node_type = ilist_node_impl<OptionsT>;
static node_type *getNodePtr(pointer N) {
return NodeAccess::getNodePtr<OptionsT>(N);
}
+
static const node_type *getNodePtr(const_pointer N) {
return NodeAccess::getNodePtr<OptionsT>(N);
}
+
static pointer getValuePtr(node_type *N) {
return NodeAccess::getValuePtr<OptionsT>(N);
}
+
static const_pointer getValuePtr(const node_type *N) {
return NodeAccess::getValuePtr<OptionsT>(N);
}
};
+
} // end namespace ilist_detail
template <class OptionsT>
@@ -265,6 +279,7 @@ public:
getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));
return List.getPrevNode(*static_cast<NodeTy *>(this));
}
+
/// \brief Get the previous node, or \c nullptr for the list head.
const NodeTy *getPrevNode() const {
return const_cast<ilist_node_with_parent *>(this)->getPrevNode();
@@ -278,6 +293,7 @@ public:
getNodeParent()->*(ParentTy::getSublistAccess((NodeTy *)nullptr));
return List.getNextNode(*static_cast<NodeTy *>(this));
}
+
/// \brief Get the next node, or \c nullptr for the list tail.
const NodeTy *getNextNode() const {
return const_cast<ilist_node_with_parent *>(this)->getNextNode();
@@ -285,6 +301,6 @@ public:
/// @}
};
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_ADT_ILIST_NODE_H
diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h
index 28dcdf9613ef..15720a67c047 100644
--- a/include/llvm/ADT/iterator.h
+++ b/include/llvm/ADT/iterator.h
@@ -11,9 +11,11 @@
#define LLVM_ADT_ITERATOR_H
#include "llvm/ADT/iterator_range.h"
+#include <algorithm>
#include <cstddef>
#include <iterator>
#include <type_traits>
+#include <utility>
namespace llvm {
@@ -206,7 +208,7 @@ template <
class iterator_adaptor_base
: public iterator_facade_base<DerivedT, IteratorCategoryT, T,
DifferenceTypeT, PointerT, ReferenceT> {
- typedef typename iterator_adaptor_base::iterator_facade_base BaseT;
+ using BaseT = typename iterator_adaptor_base::iterator_facade_base;
protected:
WrappedIteratorT I;
@@ -221,7 +223,7 @@ protected:
const WrappedIteratorT &wrapped() const { return I; }
public:
- typedef DifferenceTypeT difference_type;
+ using difference_type = DifferenceTypeT;
DerivedT &operator+=(difference_type n) {
static_assert(
@@ -279,7 +281,7 @@ public:
/// which is implemented with some iterator over T*s:
///
/// \code
-/// typedef pointee_iterator<SmallVectorImpl<T *>::iterator> iterator;
+/// using iterator = pointee_iterator<SmallVectorImpl<T *>::iterator>;
/// \endcode
template <typename WrappedIteratorT,
typename T = typename std::remove_reference<
diff --git a/include/llvm/ADT/simple_ilist.h b/include/llvm/ADT/simple_ilist.h
index a1ab59170840..4c7598a1acb4 100644
--- a/include/llvm/ADT/simple_ilist.h
+++ b/include/llvm/ADT/simple_ilist.h
@@ -13,9 +13,14 @@
#include "llvm/ADT/ilist_base.h"
#include "llvm/ADT/ilist_iterator.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/ilist_node_options.h"
+#include "llvm/Support/Compiler.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
+#include <functional>
+#include <iterator>
+#include <utility>
namespace llvm {
@@ -77,23 +82,23 @@ class simple_ilist
typename ilist_detail::compute_node_options<T, Options...>::type> {
static_assert(ilist_detail::check_options<Options...>::value,
"Unrecognized node option!");
- typedef
- typename ilist_detail::compute_node_options<T, Options...>::type OptionsT;
- typedef typename OptionsT::list_base_type list_base_type;
+ using OptionsT =
+ typename ilist_detail::compute_node_options<T, Options...>::type;
+ using list_base_type = typename OptionsT::list_base_type;
ilist_sentinel<OptionsT> Sentinel;
public:
- typedef typename OptionsT::value_type value_type;
- typedef typename OptionsT::pointer pointer;
- typedef typename OptionsT::reference reference;
- typedef typename OptionsT::const_pointer const_pointer;
- typedef typename OptionsT::const_reference const_reference;
- typedef ilist_iterator<OptionsT, false, false> iterator;
- typedef ilist_iterator<OptionsT, false, true> const_iterator;
- typedef ilist_iterator<OptionsT, true, false> reverse_iterator;
- typedef ilist_iterator<OptionsT, true, true> const_reverse_iterator;
- typedef size_t size_type;
- typedef ptrdiff_t difference_type;
+ using value_type = typename OptionsT::value_type;
+ using pointer = typename OptionsT::pointer;
+ using reference = typename OptionsT::reference;
+ using const_pointer = typename OptionsT::const_pointer;
+ using const_reference = typename OptionsT::const_reference;
+ using iterator = ilist_iterator<OptionsT, false, false>;
+ using const_iterator = ilist_iterator<OptionsT, false, true>;
+ using reverse_iterator = ilist_iterator<OptionsT, true, false>;
+ using const_reverse_iterator = ilist_iterator<OptionsT, true, true>;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
simple_ilist() = default;
~simple_ilist() = default;
diff --git a/include/llvm/Analysis/MemorySSA.h b/include/llvm/Analysis/MemorySSA.h
index f0bba8c4c020..462e4594266e 100644
--- a/include/llvm/Analysis/MemorySSA.h
+++ b/include/llvm/Analysis/MemorySSA.h
@@ -147,7 +147,6 @@ public:
MemoryAccess(const MemoryAccess &) = delete;
MemoryAccess &operator=(const MemoryAccess &) = delete;
- void *operator new(size_t, unsigned) = delete;
void *operator new(size_t) = delete;
BasicBlock *getBlock() const { return Block; }
@@ -232,7 +231,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MemoryAccess &MA) {
/// MemoryDef instead.
class MemoryUseOrDef : public MemoryAccess {
public:
- void *operator new(size_t, unsigned) = delete;
void *operator new(size_t) = delete;
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(MemoryAccess);
@@ -298,7 +296,6 @@ public:
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
- void *operator new(size_t, unsigned) = delete;
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryUseVal;
@@ -355,7 +352,6 @@ public:
// allocate space for exactly one operand
void *operator new(size_t s) { return User::operator new(s, 1); }
- void *operator new(size_t, unsigned) = delete;
static inline bool classof(const Value *MA) {
return MA->getValueID() == MemoryDefVal;
@@ -438,8 +434,6 @@ public:
allocHungoffUses(ReservedSpace);
}
- void *operator new(size_t, unsigned) = delete;
-
// Block iterator interface. This provides access to the list of incoming
// basic blocks, which parallels the list of incoming values.
typedef BasicBlock **block_iterator;
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index 8ee9712b93d8..2a4b768256d1 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -1214,26 +1214,31 @@ public:
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0);
const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS,
- SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+ unsigned Depth = 0) {
SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
- return getAddExpr(Ops, Flags);
+ return getAddExpr(Ops, Flags, Depth);
}
const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
- SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+ unsigned Depth = 0) {
SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2};
- return getAddExpr(Ops, Flags);
+ return getAddExpr(Ops, Flags, Depth);
}
const SCEV *getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
- SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+ unsigned Depth = 0);
const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS,
- SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+ unsigned Depth = 0) {
SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
- return getMulExpr(Ops, Flags);
+ return getMulExpr(Ops, Flags, Depth);
}
const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
- SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+ unsigned Depth = 0) {
SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2};
- return getMulExpr(Ops, Flags);
+ return getMulExpr(Ops, Flags, Depth);
}
const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS);
const SCEV *getUDivExactExpr(const SCEV *LHS, const SCEV *RHS);
@@ -1287,7 +1292,8 @@ public:
/// Return LHS-RHS. Minus is represented in SCEV as A+B*-1.
const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
- SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
+ SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+ unsigned Depth = 0);
/// Return a SCEV corresponding to a conversion of the input value to the
/// specified type. If the type must be extended, it is zero extended.
@@ -1693,10 +1699,14 @@ private:
bool doesIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, bool IsSigned,
bool NoWrap);
- /// Get add expr already created or create a new one
+ /// Get add expr already created or create a new one.
const SCEV *getOrCreateAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags);
+ /// Get mul expr already created or create a new one.
+ const SCEV *getOrCreateMulExpr(SmallVectorImpl<const SCEV *> &Ops,
+ SCEV::NoWrapFlags Flags);
+
private:
FoldingSet<SCEV> UniqueSCEVs;
FoldingSet<SCEVPredicate> UniquePreds;
diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h
index cd8c2cd24244..af2ebb7b6b44 100644
--- a/include/llvm/Analysis/TargetTransformInfo.h
+++ b/include/llvm/Analysis/TargetTransformInfo.h
@@ -235,6 +235,11 @@ public:
/// starting with the sources of divergence.
bool isSourceOfDivergence(const Value *V) const;
+ // \brief Returns true for the target specific
+ // set of operations which produce uniform result
+ // even taking non-unform arguments
+ bool isAlwaysUniform(const Value *V) const;
+
/// Returns the address space ID for a target's 'flat' address space. Note
/// this is not necessarily the same as addrspace(0), which LLVM sometimes
/// refers to as the generic address space. The flat address space is a
@@ -821,6 +826,7 @@ public:
virtual int getUserCost(const User *U) = 0;
virtual bool hasBranchDivergence() = 0;
virtual bool isSourceOfDivergence(const Value *V) = 0;
+ virtual bool isAlwaysUniform(const Value *V) = 0;
virtual unsigned getFlatAddressSpace() = 0;
virtual bool isLoweredToCall(const Function *F) = 0;
virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0;
@@ -873,7 +879,7 @@ public:
virtual int getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
Type *Ty) = 0;
virtual unsigned getNumberOfRegisters(bool Vector) = 0;
- virtual unsigned getRegisterBitWidth(bool Vector) = 0;
+ virtual unsigned getRegisterBitWidth(bool Vector) const = 0;
virtual unsigned getMinVectorRegisterBitWidth() = 0;
virtual bool shouldConsiderAddressTypePromotion(
const Instruction &I, bool &AllowPromotionWithoutCommonHeader) = 0;
@@ -998,6 +1004,10 @@ public:
return Impl.isSourceOfDivergence(V);
}
+ bool isAlwaysUniform(const Value *V) override {
+ return Impl.isAlwaysUniform(V);
+ }
+
unsigned getFlatAddressSpace() override {
return Impl.getFlatAddressSpace();
}
@@ -1119,7 +1129,7 @@ public:
unsigned getNumberOfRegisters(bool Vector) override {
return Impl.getNumberOfRegisters(Vector);
}
- unsigned getRegisterBitWidth(bool Vector) override {
+ unsigned getRegisterBitWidth(bool Vector) const override {
return Impl.getRegisterBitWidth(Vector);
}
unsigned getMinVectorRegisterBitWidth() override {
diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h
index 72de7c12eb3e..24ac3b1213e1 100644
--- a/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -177,6 +177,8 @@ public:
bool isSourceOfDivergence(const Value *V) { return false; }
+ bool isAlwaysUniform(const Value *V) { return false; }
+
unsigned getFlatAddressSpace () {
return -1;
}
@@ -320,7 +322,7 @@ public:
unsigned getNumberOfRegisters(bool Vector) { return 8; }
- unsigned getRegisterBitWidth(bool Vector) { return 32; }
+ unsigned getRegisterBitWidth(bool Vector) const { return 32; }
unsigned getMinVectorRegisterBitWidth() { return 128; }
diff --git a/include/llvm/Analysis/TypeMetadataUtils.h b/include/llvm/Analysis/TypeMetadataUtils.h
index 17906ba4e392..422e153a5a78 100644
--- a/include/llvm/Analysis/TypeMetadataUtils.h
+++ b/include/llvm/Analysis/TypeMetadataUtils.h
@@ -20,6 +20,13 @@
namespace llvm {
+/// The type of CFI jumptable needed for a function.
+enum CfiFunctionLinkage {
+ CFL_Definition = 0,
+ CFL_Declaration = 1,
+ CFL_WeakDeclaration = 2
+};
+
/// A call site that could be devirtualized.
struct DevirtCallSite {
/// The offset from the address point to the virtual function.
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index 612779b1ce86..e953ec8ab6ab 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -249,8 +249,8 @@ template <typename T> class ArrayRef;
};
/// 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.
+ /// If successful \p Index will point to a ConstantDataArray info object
+ /// with an appropriate offset.
bool getConstantDataArrayInfo(const Value *V, ConstantDataArraySlice &Slice,
unsigned ElementSize, uint64_t Offset = 0);
diff --git a/include/llvm/BinaryFormat/ELF.h b/include/llvm/BinaryFormat/ELF.h
index 3724f555c283..a4450ee13b40 100644
--- a/include/llvm/BinaryFormat/ELF.h
+++ b/include/llvm/BinaryFormat/ELF.h
@@ -1,4 +1,4 @@
-//===-- llvm/BinaryFormat/ELF.h - ELF constants and structures --*- C++ -*-===//
+//===- llvm/BinaryFormat/ELF.h - ELF constants and structures ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,27 +20,25 @@
#ifndef LLVM_BINARYFORMAT_ELF_H
#define LLVM_BINARYFORMAT_ELF_H
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/DataTypes.h"
+#include <cstdint>
#include <cstring>
namespace llvm {
-
namespace ELF {
-typedef uint32_t Elf32_Addr; // Program address
-typedef uint32_t Elf32_Off; // File offset
-typedef uint16_t Elf32_Half;
-typedef uint32_t Elf32_Word;
-typedef int32_t Elf32_Sword;
+using Elf32_Addr = uint32_t; // Program address
+using Elf32_Off = uint32_t; // File offset
+using Elf32_Half = uint16_t;
+using Elf32_Word = uint32_t;
+using Elf32_Sword = int32_t;
-typedef uint64_t Elf64_Addr;
-typedef uint64_t Elf64_Off;
-typedef uint16_t Elf64_Half;
-typedef uint32_t Elf64_Word;
-typedef int32_t Elf64_Sword;
-typedef uint64_t Elf64_Xword;
-typedef int64_t Elf64_Sxword;
+using Elf64_Addr = uint64_t;
+using Elf64_Off = uint64_t;
+using Elf64_Half = uint16_t;
+using Elf64_Word = uint32_t;
+using Elf64_Sword = int32_t;
+using Elf64_Xword = uint64_t;
+using Elf64_Sxword = int64_t;
// Object file magic string.
static const char ElfMagic[] = {0x7f, 'E', 'L', 'F', '\0'};
@@ -75,9 +73,11 @@ struct Elf32_Ehdr {
Elf32_Half e_shentsize; // Size of an entry in the section header table
Elf32_Half e_shnum; // Number of entries in the section header table
Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table
+
bool checkMagic() const {
return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0;
}
+
unsigned char getFileClass() const { return e_ident[EI_CLASS]; }
unsigned char getDataEncoding() const { return e_ident[EI_DATA]; }
};
@@ -99,9 +99,11 @@ struct Elf64_Ehdr {
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
+
bool checkMagic() const {
return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0;
}
+
unsigned char getFileClass() const { return e_ident[EI_CLASS]; }
unsigned char getDataEncoding() const { return e_ident[EI_DATA]; }
};
@@ -683,6 +685,7 @@ enum : unsigned {
SHT_GROUP = 17, // Section group.
SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries.
SHT_LOOS = 0x60000000, // Lowest operating system-specific type.
+ SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table.
SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes.
SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table.
SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions.
@@ -1356,7 +1359,6 @@ enum {
};
} // end namespace ELF
-
} // end namespace llvm
-#endif
+#endif // LLVM_BINARYFORMAT_ELF_H
diff --git a/include/llvm/Bitcode/BitcodeReader.h b/include/llvm/Bitcode/BitcodeReader.h
index 61e4f6351b19..0e17e9a0a278 100644
--- a/include/llvm/Bitcode/BitcodeReader.h
+++ b/include/llvm/Bitcode/BitcodeReader.h
@@ -42,6 +42,12 @@ namespace llvm {
struct BitcodeFileContents;
+ /// Basic information extracted from a bitcode module to be used for LTO.
+ struct BitcodeLTOInfo {
+ bool IsThinLTO;
+ bool HasSummary;
+ };
+
/// Represents a module in a bitcode file.
class BitcodeModule {
// This covers the identification (if present) and module blocks.
@@ -90,15 +96,17 @@ namespace llvm {
/// Read the entire bitcode module and return it.
Expected<std::unique_ptr<Module>> parseModule(LLVMContext &Context);
- /// Check if the given bitcode buffer contains a summary block.
- Expected<bool> hasSummary();
+ /// Returns information about the module to be used for LTO: whether to
+ /// compile with ThinLTO, and whether it has a summary.
+ Expected<BitcodeLTOInfo> getLTOInfo();
/// Parse the specified bitcode buffer, returning the module summary index.
Expected<std::unique_ptr<ModuleSummaryIndex>> getSummary();
/// Parse the specified bitcode buffer and merge its module summary index
/// into CombinedIndex.
- Error readSummary(ModuleSummaryIndex &CombinedIndex, unsigned ModuleId);
+ Error readSummary(ModuleSummaryIndex &CombinedIndex, StringRef ModulePath,
+ uint64_t ModuleId);
};
struct BitcodeFileContents {
@@ -147,8 +155,8 @@ namespace llvm {
Expected<std::unique_ptr<Module>> parseBitcodeFile(MemoryBufferRef Buffer,
LLVMContext &Context);
- /// Check if the given bitcode buffer contains a summary block.
- Expected<bool> hasGlobalValueSummary(MemoryBufferRef Buffer);
+ /// Returns LTO information for the specified bitcode file.
+ Expected<BitcodeLTOInfo> getBitcodeLTOInfo(MemoryBufferRef Buffer);
/// Parse the specified bitcode buffer, returning the module summary index.
Expected<std::unique_ptr<ModuleSummaryIndex>>
@@ -157,7 +165,7 @@ namespace llvm {
/// Parse the specified bitcode buffer and merge the index into CombinedIndex.
Error readModuleSummaryIndex(MemoryBufferRef Buffer,
ModuleSummaryIndex &CombinedIndex,
- unsigned ModuleId);
+ uint64_t ModuleId);
/// Parse the module summary index out of an IR file and return the module
/// summary index object if found, or an empty summary if not. If Path refers
diff --git a/include/llvm/Bitcode/BitcodeWriter.h b/include/llvm/Bitcode/BitcodeWriter.h
index 23b5ae87b278..7c3c4b2e0cbd 100644
--- a/include/llvm/Bitcode/BitcodeWriter.h
+++ b/include/llvm/Bitcode/BitcodeWriter.h
@@ -67,6 +67,10 @@ namespace llvm {
void writeModule(const Module *M, bool ShouldPreserveUseListOrder = false,
const ModuleSummaryIndex *Index = nullptr,
bool GenerateHash = false, ModuleHash *ModHash = nullptr);
+
+ void writeIndex(
+ const ModuleSummaryIndex *Index,
+ const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex);
};
/// \brief Write the specified module to the specified raw output stream.
diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h
index a643bfd1dcea..4e3e177cac8f 100644
--- a/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/include/llvm/Bitcode/LLVMBitCodes.h
@@ -240,6 +240,14 @@ enum GlobalValueSummarySymtabCodes {
// summaries, but it can also appear in per-module summaries for PGO data.
// [valueid, guid]
FS_VALUE_GUID = 16,
+ // The list of local functions with CFI jump tables. Function names are
+ // strings in strtab.
+ // [n * name]
+ FS_CFI_FUNCTION_DEFS = 17,
+ // The list of external functions with CFI jump tables. Function names are
+ // strings in strtab.
+ // [n * name]
+ FS_CFI_FUNCTION_DECLS = 18,
};
enum MetadataCodes {
diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h
index 9e33df6b55ec..5eb7a0f61eec 100644
--- a/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/include/llvm/CodeGen/BasicTTIImpl.h
@@ -93,6 +93,8 @@ public:
bool isSourceOfDivergence(const Value *V) { return false; }
+ bool isAlwaysUniform(const Value *V) { return false; }
+
unsigned getFlatAddressSpace() {
// Return an invalid address space.
return -1;
@@ -346,7 +348,7 @@ public:
unsigned getNumberOfRegisters(bool Vector) { return Vector ? 0 : 1; }
- unsigned getRegisterBitWidth(bool Vector) { return 32; }
+ unsigned getRegisterBitWidth(bool Vector) const { return 32; }
/// Estimate the overhead of scalarizing an instruction. Insert and Extract
/// are set if the result needs to be inserted and/or extracted from vectors.
diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h
index 7d7c3e8cfd22..f32a58915118 100644
--- a/include/llvm/CodeGen/FunctionLoweringInfo.h
+++ b/include/llvm/CodeGen/FunctionLoweringInfo.h
@@ -82,6 +82,11 @@ public:
DenseMap<std::pair<const MachineBasicBlock *, const Value *>, unsigned>
SwiftErrorVRegUpwardsUse;
+ /// A map from instructions that define/use a swifterror value to the virtual
+ /// register that represents that def/use.
+ llvm::DenseMap<PointerIntPair<const Instruction *, 1, bool>, unsigned>
+ SwiftErrorVRegDefUses;
+
/// The swifterror argument of the current function.
const Value *SwiftErrorArg;
@@ -101,6 +106,13 @@ public:
void setCurrentSwiftErrorVReg(const MachineBasicBlock *MBB, const Value *,
unsigned);
+ /// Get or create the swifterror value virtual register for a def of a
+ /// swifterror by an instruction.
+ std::pair<unsigned, bool> getOrCreateSwiftErrorVRegDefAt(const Instruction *);
+ std::pair<unsigned, bool>
+ getOrCreateSwiftErrorVRegUseAt(const Instruction *, const MachineBasicBlock *,
+ const Value *);
+
/// ValueMap - Since we emit code for the function a basic block at a time,
/// we must remember which virtual registers hold the values for
/// cross-basic-block values.
diff --git a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 3148e70b56f8..5197ba869c0a 100644
--- a/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -21,9 +21,11 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
#define LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
+#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/LowLevelType.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/RuntimeLibcalls.h"
namespace llvm {
// Forward declarations.
@@ -99,6 +101,12 @@ private:
const LegalizerInfo &LI;
};
+/// Helper function that replaces \p MI with a libcall.
+LegalizerHelper::LegalizeResult
+replaceWithLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
+ RTLIB::Libcall Libcall, const CallLowering::ArgInfo &Result,
+ ArrayRef<CallLowering::ArgInfo> Args);
+
} // End namespace llvm.
#endif
diff --git a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index db72f78c8321..4e7b8350038b 100644
--- a/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -40,8 +40,8 @@ class MachineIRBuilder {
MachineFunction *MF;
/// Information used to access the description of the opcodes.
const TargetInstrInfo *TII;
- /// Information used to verify types are consistent.
- const MachineRegisterInfo *MRI;
+ /// Information used to verify types are consistent and to create virtual registers.
+ MachineRegisterInfo *MRI;
/// Debug location to be set to any instruction we create.
DebugLoc DL;
@@ -229,6 +229,26 @@ public:
MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0,
unsigned Op1);
+ /// Materialize and insert \p Res<def> = G_GEP \p Op0, (G_CONSTANT \p Value)
+ ///
+ /// G_GEP adds \p Value bytes to the pointer specified by \p Op0,
+ /// storing the resulting pointer in \p Res. If \p Value is zero then no
+ /// G_GEP or G_CONSTANT will be created and \pre Op0 will be assigned to
+ /// \p Res.
+ ///
+ /// \pre setBasicBlock or setMI must have been called.
+ /// \pre \p Op0 must be a generic virtual register with pointer type.
+ /// \pre \p ValueTy must be a scalar type.
+ /// \pre \p Res must be 0. This is to detect confusion between
+ /// materializeGEP() and buildGEP().
+ /// \post \p Res will either be a new generic virtual register of the same
+ /// type as \p Op0 or \p Op0 itself.
+ ///
+ /// \return a MachineInstrBuilder for the newly created instruction.
+ Optional<MachineInstrBuilder> materializeGEP(unsigned &Res, unsigned Op0,
+ const LLT &ValueTy,
+ uint64_t Value);
+
/// Build and insert \p Res<def> = G_PTR_MASK \p Op0, \p NumBits
///
/// G_PTR_MASK clears the low bits of a pointer operand without destroying its
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index ddfabb0c44d6..8c3aacaa8efc 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -333,12 +333,12 @@ namespace RTLIB {
MEMSET,
MEMMOVE,
- // ELEMENT-WISE ATOMIC MEMORY
- MEMCPY_ELEMENT_ATOMIC_1,
- MEMCPY_ELEMENT_ATOMIC_2,
- MEMCPY_ELEMENT_ATOMIC_4,
- MEMCPY_ELEMENT_ATOMIC_8,
- MEMCPY_ELEMENT_ATOMIC_16,
+ // ELEMENT-WISE UNORDERED-ATOMIC MEMORY of different element sizes
+ MEMCPY_ELEMENT_UNORDERED_ATOMIC_1,
+ MEMCPY_ELEMENT_UNORDERED_ATOMIC_2,
+ MEMCPY_ELEMENT_UNORDERED_ATOMIC_4,
+ MEMCPY_ELEMENT_UNORDERED_ATOMIC_8,
+ MEMCPY_ELEMENT_UNORDERED_ATOMIC_16,
// EXCEPTION HANDLING
UNWIND_RESUME,
@@ -511,9 +511,10 @@ namespace RTLIB {
/// UNKNOWN_LIBCALL if there is none.
Libcall getSYNC(unsigned Opc, MVT VT);
- /// getMEMCPY_ELEMENT_ATOMIC - Return MEMCPY_ELEMENT_ATOMIC_* value for the
- /// given element size or UNKNOW_LIBCALL if there is none.
- Libcall getMEMCPY_ELEMENT_ATOMIC(uint64_t ElementSize);
+ /// getMEMCPY_ELEMENT_UNORDERED_ATOMIC - Return
+ /// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
+ /// UNKNOW_LIBCALL if there is none.
+ Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
}
}
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index 2ef7796a4a07..f3f3003b7e20 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -1217,6 +1217,12 @@ public:
void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To,
unsigned Num);
+ /// If an existing load has uses of its chain, create a token factor node with
+ /// that chain and the new memory node's chain and update users of the old
+ /// chain to the token factor. This ensures that the new memory node will have
+ /// the same relative memory dependency position as the old load.
+ void makeEquivalentMemoryOrdering(LoadSDNode *Old, SDValue New);
+
/// Topological-sort the AllNodes list and a
/// assign a unique node id for each node in the DAG based on their
/// topological order. Returns the number of nodes.
diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 106a084a95c0..e4d3cc9cecfc 100644
--- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -42,9 +42,8 @@ public:
~TargetLoweringObjectFileELF() override = default;
/// Emit Obj-C garbage collection and linker options.
- void emitModuleFlags(MCStreamer &Streamer,
- ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
- const TargetMachine &TM) const override;
+ void emitModuleMetadata(MCStreamer &Streamer, Module &M,
+ const TargetMachine &TM) const override;
void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
const MCSymbol *Sym) const override;
@@ -99,9 +98,8 @@ public:
void Initialize(MCContext &Ctx, const TargetMachine &TM) override;
/// Emit the module flags that specify the garbage collection information.
- void emitModuleFlags(MCStreamer &Streamer,
- ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
- const TargetMachine &TM) const override;
+ void emitModuleMetadata(MCStreamer &Streamer, Module &M,
+ const TargetMachine &TM) const override;
MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind,
const TargetMachine &TM) const override;
@@ -155,9 +153,8 @@ public:
const TargetMachine &TM) const override;
/// Emit Obj-C garbage collection and linker options.
- void emitModuleFlags(MCStreamer &Streamer,
- ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
- const TargetMachine &TM) const override;
+ void emitModuleMetadata(MCStreamer &Streamer, Module &M,
+ const TargetMachine &TM) const override;
MCSection *getStaticCtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;
diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h
index 251c9d1ae62c..6820e26b754c 100644
--- a/include/llvm/DebugInfo/CodeView/CodeView.h
+++ b/include/llvm/DebugInfo/CodeView/CodeView.h
@@ -418,6 +418,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(ProcSymFlags)
/// Corresponds to COMPILESYM2::Flags bitfield.
enum class CompileSym2Flags : uint32_t {
+ None = 0,
+ SourceLanguageMask = 0xFF,
EC = 1 << 8,
NoDbgInfo = 1 << 9,
LTCG = 1 << 10,
@@ -432,6 +434,8 @@ CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym2Flags)
/// Corresponds to COMPILESYM3::Flags bitfield.
enum class CompileSym3Flags : uint32_t {
+ None = 0,
+ SourceLanguageMask = 0xFF,
EC = 1 << 8,
NoDbgInfo = 1 << 9,
LTCG = 1 << 10,
@@ -448,6 +452,7 @@ enum class CompileSym3Flags : uint32_t {
CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(CompileSym3Flags)
enum class ExportFlags : uint16_t {
+ None = 0,
IsConstant = 1 << 0,
IsData = 1 << 1,
IsPrivate = 1 << 2,
diff --git a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
index 686b5c4f242e..1e329c7c3f14 100644
--- a/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
+++ b/include/llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h
@@ -49,6 +49,7 @@ public:
Error commit(BinaryStreamWriter &Writer) const override;
void addFrameData(const FrameData &Frame);
+ void setFrames(ArrayRef<FrameData> Frames);
private:
std::vector<FrameData> Frames;
diff --git a/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h b/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h
index c9b062717baa..7484af663105 100644
--- a/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h
+++ b/include/llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h
@@ -19,7 +19,7 @@
namespace llvm {
namespace codeview {
-class DebugInlineeLinesSubsectionsRef;
+class DebugInlineeLinesSubsectionRef;
class DebugChecksumsSubsection;
enum class InlineeLinesSignature : uint32_t {
diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
index 49a269d92e35..694731742064 100644
--- a/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
+++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
@@ -49,13 +49,13 @@ private:
class DebugSubsectionRecordBuilder {
public:
- DebugSubsectionRecordBuilder(std::unique_ptr<DebugSubsection> Subsection,
+ DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection,
CodeViewContainer Container);
uint32_t calculateSerializedLength();
Error commit(BinaryStreamWriter &Writer) const;
private:
- std::unique_ptr<DebugSubsection> Subsection;
+ std::shared_ptr<DebugSubsection> Subsection;
CodeViewContainer Container;
};
@@ -64,6 +64,9 @@ private:
template <> struct VarStreamArrayExtractor<codeview::DebugSubsectionRecord> {
Error operator()(BinaryStreamRef Stream, uint32_t &Length,
codeview::DebugSubsectionRecord &Info) {
+ // FIXME: We need to pass the container type through to this function. In
+ // practice this isn't super important since the subsection header describes
+ // its length and we can just skip it. It's more important when writing.
if (auto EC = codeview::DebugSubsectionRecord::initialize(
Stream, Info, codeview::CodeViewContainer::Pdb))
return EC;
diff --git a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
index d4a3d9195a36..75f749dfa933 100644
--- a/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
@@ -12,6 +12,7 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/Support/Error.h"
#include <cstdint>
@@ -30,56 +31,7 @@ class DebugStringTableSubsectionRef;
class DebugSymbolRVASubsectionRef;
class DebugSymbolsSubsectionRef;
class DebugUnknownSubsectionRef;
-
-struct DebugSubsectionState {
-public:
- // If no subsections are known about initially, we find as much as we can.
- DebugSubsectionState();
-
- // If only a string table subsection is given, we find a checksums subsection.
- explicit DebugSubsectionState(const DebugStringTableSubsectionRef &Strings);
-
- // If both subsections are given, we don't need to find anything.
- DebugSubsectionState(const DebugStringTableSubsectionRef &Strings,
- const DebugChecksumsSubsectionRef &Checksums);
-
- template <typename T> void initialize(T &&FragmentRange) {
- for (const DebugSubsectionRecord &R : FragmentRange) {
- if (Strings && Checksums)
- return;
- if (R.kind() == DebugSubsectionKind::FileChecksums) {
- initializeChecksums(R);
- continue;
- }
- if (R.kind() == DebugSubsectionKind::StringTable && !Strings) {
- // While in practice we should never encounter a string table even
- // though the string table is already initialized, in theory it's
- // possible. PDBs are supposed to have one global string table and
- // then this subsection should not appear. Whereas object files are
- // supposed to have this subsection appear exactly once. However,
- // for testing purposes it's nice to be able to test this subsection
- // independently of one format or the other, so for some tests we
- // manually construct a PDB that contains this subsection in addition
- // to a global string table.
- initializeStrings(R);
- continue;
- }
- }
- }
-
- const DebugStringTableSubsectionRef &strings() const { return *Strings; }
- const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; }
-
-private:
- void initializeStrings(const DebugSubsectionRecord &SR);
- void initializeChecksums(const DebugSubsectionRecord &FCR);
-
- std::unique_ptr<DebugStringTableSubsectionRef> OwnedStrings;
- std::unique_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
-
- const DebugStringTableSubsectionRef *Strings = nullptr;
- const DebugChecksumsSubsectionRef *Checksums = nullptr;
-};
+class StringsAndChecksumsRef;
class DebugSubsectionVisitor {
public:
@@ -89,38 +41,38 @@ public:
return Error::success();
}
virtual Error visitLines(DebugLinesSubsectionRef &Lines,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error
visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error
visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error visitStringTable(DebugStringTableSubsectionRef &ST,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error visitSymbols(DebugSymbolsSubsectionRef &CSE,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error visitFrameData(DebugFrameDataSubsectionRef &FD,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
virtual Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs,
- const DebugSubsectionState &State) = 0;
+ const StringsAndChecksumsRef &State) = 0;
};
Error visitDebugSubsection(const DebugSubsectionRecord &R,
DebugSubsectionVisitor &V,
- const DebugSubsectionState &State);
+ const StringsAndChecksumsRef &State);
namespace detail {
template <typename T>
Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
- DebugSubsectionState &State) {
+ StringsAndChecksumsRef &State) {
State.initialize(std::forward<T>(FragmentRange));
for (const DebugSubsectionRecord &L : FragmentRange) {
@@ -133,7 +85,7 @@ Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
template <typename T>
Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
- DebugSubsectionState State;
+ StringsAndChecksumsRef State;
return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
State);
}
@@ -141,7 +93,7 @@ Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
template <typename T>
Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
const DebugStringTableSubsectionRef &Strings) {
- DebugSubsectionState State(Strings);
+ StringsAndChecksumsRef State(Strings);
return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
State);
}
@@ -150,7 +102,7 @@ template <typename T>
Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
const DebugStringTableSubsectionRef &Strings,
const DebugChecksumsSubsectionRef &Checksums) {
- DebugSubsectionState State(Strings, Checksums);
+ StringsAndChecksumsRef State(Strings, Checksums);
return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
State);
}
diff --git a/include/llvm/DebugInfo/CodeView/Formatters.h b/include/llvm/DebugInfo/CodeView/Formatters.h
index 37a91098a8b6..1fbb0dd6f9b0 100644
--- a/include/llvm/DebugInfo/CodeView/Formatters.h
+++ b/include/llvm/DebugInfo/CodeView/Formatters.h
@@ -12,7 +12,10 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
namespace llvm {
namespace codeview {
@@ -35,6 +38,20 @@ inline detail::GuidAdapter fmt_guid(ArrayRef<uint8_t> Item) {
return detail::GuidAdapter(Item);
}
}
+
+template <> struct format_provider<codeview::TypeIndex> {
+public:
+ static void format(const codeview::TypeIndex &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ if (V.isNoneType())
+ Stream << "<no type>";
+ else {
+ Stream << formatv("{0:X+4}", V.getIndex());
+ if (V.isSimple())
+ Stream << " (" << codeview::TypeIndex::simpleTypeName(V) << ")";
+ }
+ }
+};
}
#endif
diff --git a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
new file mode 100644
index 000000000000..708b317164fc
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
@@ -0,0 +1,106 @@
+//===- StringsAndChecksums.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_STRINGS_AND_CHECKSUMS_H
+#define LLVM_DEBUGINFO_CODEVIEW_STRINGS_AND_CHECKSUMS_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+
+#include <memory>
+
+namespace llvm {
+namespace codeview {
+
+class DebugSubsectionRecord;
+class DebugChecksumsSubsectionRef;
+class DebugStringTableSubsectionRef;
+class DebugChecksumsSubsection;
+class DebugStringTableSubsection;
+
+class StringsAndChecksumsRef {
+public:
+ // If no subsections are known about initially, we find as much as we can.
+ StringsAndChecksumsRef();
+
+ // If only a string table subsection is given, we find a checksums subsection.
+ explicit StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings);
+
+ // If both subsections are given, we don't need to find anything.
+ StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums);
+
+ void setChecksums(const DebugChecksumsSubsectionRef &CS);
+
+ template <typename T> void initialize(T &&FragmentRange) {
+ for (const DebugSubsectionRecord &R : FragmentRange) {
+ if (Strings && Checksums)
+ return;
+ if (R.kind() == DebugSubsectionKind::FileChecksums) {
+ initializeChecksums(R);
+ continue;
+ }
+ if (R.kind() == DebugSubsectionKind::StringTable && !Strings) {
+ // While in practice we should never encounter a string table even
+ // though the string table is already initialized, in theory it's
+ // possible. PDBs are supposed to have one global string table and
+ // then this subsection should not appear. Whereas object files are
+ // supposed to have this subsection appear exactly once. However,
+ // for testing purposes it's nice to be able to test this subsection
+ // independently of one format or the other, so for some tests we
+ // manually construct a PDB that contains this subsection in addition
+ // to a global string table.
+ initializeStrings(R);
+ continue;
+ }
+ }
+ }
+
+ const DebugStringTableSubsectionRef &strings() const { return *Strings; }
+ const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; }
+
+ bool hasStrings() const { return Strings != nullptr; }
+ bool hasChecksums() const { return Checksums != nullptr; }
+
+private:
+ void initializeStrings(const DebugSubsectionRecord &SR);
+ void initializeChecksums(const DebugSubsectionRecord &FCR);
+
+ std::unique_ptr<DebugStringTableSubsectionRef> OwnedStrings;
+ std::unique_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
+
+ const DebugStringTableSubsectionRef *Strings = nullptr;
+ const DebugChecksumsSubsectionRef *Checksums = nullptr;
+};
+
+class StringsAndChecksums {
+public:
+ using StringsPtr = std::shared_ptr<DebugStringTableSubsection>;
+ using ChecksumsPtr = std::shared_ptr<DebugChecksumsSubsection>;
+ // If no subsections are known about initially, we find as much as we can.
+ StringsAndChecksums() {}
+
+ void setStrings(const StringsPtr &SP) { Strings = SP; }
+ void setChecksums(const ChecksumsPtr &CP) { Checksums = CP; }
+
+ const StringsPtr &strings() const { return Strings; }
+ const ChecksumsPtr &checksums() const { return Checksums; }
+
+ bool hasStrings() const { return Strings != nullptr; }
+ bool hasChecksums() const { return Checksums != nullptr; }
+
+private:
+ StringsPtr Strings;
+ ChecksumsPtr Checksums;
+};
+
+} // namespace codeview
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index a3e4dff647bd..5f85ed28cb3a 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -363,7 +363,7 @@ public:
: SymbolRecord(SymbolRecordKind::PublicSym32),
RecordOffset(RecordOffset) {}
- uint32_t Index;
+ TypeIndex Index;
uint32_t Offset;
uint16_t Segment;
StringRef Name;
@@ -379,7 +379,7 @@ public:
: SymbolRecord(SymbolRecordKind::RegisterSym),
RecordOffset(RecordOffset) {}
- uint32_t Index;
+ TypeIndex Index;
RegisterId Register;
StringRef Name;
@@ -679,7 +679,7 @@ public:
: SymbolRecord(SymbolRecordKind::FileStaticSym),
RecordOffset(RecordOffset) {}
- uint32_t Index;
+ TypeIndex Index;
uint32_t ModFilenameOffset;
LocalSymFlags Flags;
StringRef Name;
@@ -814,7 +814,7 @@ public:
uint32_t CodeOffset;
uint16_t Register;
- uint8_t CookieKind;
+ FrameCookieKind CookieKind;
uint8_t Flags;
uint32_t RecordOffset;
@@ -871,7 +871,7 @@ public:
uint32_t Offset;
TypeIndex Type;
- uint16_t Register;
+ RegisterId Register;
StringRef Name;
uint32_t RecordOffset;
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndex.h b/include/llvm/DebugInfo/CodeView/TypeIndex.h
index 31eed7d3e877..10d51c2d6244 100644
--- a/include/llvm/DebugInfo/CodeView/TypeIndex.h
+++ b/include/llvm/DebugInfo/CodeView/TypeIndex.h
@@ -248,6 +248,8 @@ public:
return A.toArrayIndex() - B.toArrayIndex();
}
+ static StringRef simpleTypeName(TypeIndex TI);
+
private:
support::ulittle32_t Index;
};
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 72793e97b60d..3012b39dcc52 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -50,6 +50,10 @@ public:
: AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {}
bool extract();
+ uint32_t getNumBuckets();
+ uint32_t getNumHashes();
+ uint32_t getSizeHdr();
+ uint32_t getHeaderDataLength();
void dump(raw_ostream &OS) const;
};
diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index b9f14be85926..9eb5c45faba8 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -20,6 +20,7 @@ struct DWARFAttribute;
class DWARFContext;
class DWARFDie;
class DWARFUnit;
+class DWARFAcceleratorTable;
/// A class that verifies DWARF debug information given a DWARF Context.
class DWARFVerifier {
@@ -29,8 +30,9 @@ class DWARFVerifier {
/// can verify each reference points to a valid DIE and not an offset that
/// lies between to valid DIEs.
std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets;
- uint32_t NumDebugInfoErrors;
- uint32_t NumDebugLineErrors;
+ uint32_t NumDebugInfoErrors = 0;
+ uint32_t NumDebugLineErrors = 0;
+ uint32_t NumAppleNamesErrors = 0;
/// Verifies the attribute's DWARF attribute and its value.
///
@@ -38,8 +40,8 @@ class DWARFVerifier {
/// - DW_AT_ranges values is a valid .debug_ranges offset
/// - DW_AT_stmt_list is a valid .debug_line offset
///
- /// @param Die The DWARF DIE that owns the attribute value
- /// @param AttrValue The DWARF attribute value to check
+ /// \param Die The DWARF DIE that owns the attribute value
+ /// \param AttrValue The DWARF attribute value to check
void verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue);
/// Verifies the attribute's DWARF form.
@@ -49,8 +51,8 @@ class DWARFVerifier {
/// - All DW_FORM_ref_addr values have valid .debug_info offsets
/// - All DW_FORM_strp values have valid .debug_str offsets
///
- /// @param Die The DWARF DIE that owns the attribute value
- /// @param AttrValue The DWARF attribute value to check
+ /// \param Die The DWARF DIE that owns the attribute value
+ /// \param AttrValue The DWARF attribute value to check
void verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);
/// Verifies the all valid references that were found when iterating through
@@ -75,13 +77,13 @@ class DWARFVerifier {
public:
DWARFVerifier(raw_ostream &S, DWARFContext &D)
- : OS(S), DCtx(D), NumDebugInfoErrors(0), NumDebugLineErrors(0) {}
+ : OS(S), DCtx(D) {}
/// Verify the information in the .debug_info section.
///
/// Any errors are reported to the stream that was this object was
/// constructed with.
///
- /// @return True if the .debug_info verifies successfully, false otherwise.
+ /// \returns true if the .debug_info verifies successfully, false otherwise.
bool handleDebugInfo();
/// Verify the information in the .debug_line section.
@@ -89,8 +91,16 @@ public:
/// Any errors are reported to the stream that was this object was
/// constructed with.
///
- /// @return True if the .debug_line verifies successfully, false otherwise.
+ /// \returns true if the .debug_line verifies successfully, false otherwise.
bool handleDebugLine();
+
+ /// Verify the information in the .apple_names accelerator table.
+ ///
+ /// Any errors are reported to the stream that was this object was
+ /// constructed with.
+ ///
+ /// \returns true if the .apple_names verifies successfully, false otherwise.
+ bool handleAppleNames();
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
index 2ff166b24e68..a89e26ae943c 100644
--- a/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
@@ -50,12 +50,14 @@ public:
void addSymbol(codeview::CVSymbol Symbol);
void
- addDebugSubsection(std::unique_ptr<codeview::DebugSubsection> Subsection);
+ addDebugSubsection(std::shared_ptr<codeview::DebugSubsection> Subsection);
uint16_t getStreamIndex() const;
StringRef getModuleName() const { return ModuleName; }
StringRef getObjFileName() const { return ObjFileName; }
+ unsigned getModuleIndex() const { return Layout.Mod; }
+
ArrayRef<std::string> source_files() const {
return makeArrayRef(SourceFiles);
}
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
index bcf1cff8f6e5..2885081628f6 100644
--- a/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/BinaryStreamRef.h"
@@ -21,6 +22,7 @@
#include <vector>
namespace llvm {
+namespace codeview {}
namespace pdb {
class DbiModuleList;
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index e116f314ac0e..aeb2e2ab026a 100644
--- a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -49,7 +49,6 @@ public:
void setPdbDllRbld(uint16_t R);
void setFlags(uint16_t F);
void setMachineType(PDB_Machine M);
- void setSectionContribs(ArrayRef<SectionContrib> SecMap);
void setSectionMap(ArrayRef<SecMapEntry> SecMap);
// Add given bytes as a new stream.
@@ -65,10 +64,8 @@ public:
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer);
- // A helper function to create Section Contributions from COFF input
- // section headers.
- static std::vector<SectionContrib>
- createSectionContribs(ArrayRef<llvm::object::coff_section> SecHdrs);
+ void addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
+ const llvm::object::coff_section *SecHdr);
// A helper function to create a Section Map from a COFF section header.
static std::vector<SecMapEntry>
@@ -112,7 +109,7 @@ private:
WritableBinaryStreamRef NamesBuffer;
MutableBinaryByteStream FileInfoBuffer;
- ArrayRef<SectionContrib> SectionContribs;
+ std::vector<SectionContrib> SectionContribs;
ArrayRef<SecMapEntry> SectionMap;
llvm::SmallVector<DebugStream, (int)DbgHeaderType::Max> DbgStreams;
};
diff --git a/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/include/llvm/DebugInfo/PDB/Native/InfoStream.h
index 1c38c2b6194f..fc91fc7097bd 100644
--- a/include/llvm/DebugInfo/PDB/Native/InfoStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/InfoStream.h
@@ -35,6 +35,7 @@ public:
uint32_t getStreamSize() const;
+ bool containsIdStream() const;
PdbRaw_ImplVer getVersion() const;
uint32_t getSignature() const;
uint32_t getAge() const;
diff --git a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
index a8121978d882..c744696ae250 100644
--- a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
@@ -31,6 +31,7 @@ class ModuleDebugStreamRef {
public:
ModuleDebugStreamRef(const DbiModuleDescriptor &Module,
std::unique_ptr<msf::MappedBlockStream> Stream);
+ ModuleDebugStreamRef(ModuleDebugStreamRef &&Other) = default;
~ModuleDebugStreamRef();
Error reload();
@@ -40,6 +41,12 @@ public:
iterator_range<codeview::CVSymbolArray::Iterator>
symbols(bool *HadError) const;
+ const codeview::CVSymbolArray &getSymbolArray() const {
+ return SymbolsSubstream;
+ }
+
+ ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = default;
+
llvm::iterator_range<DebugSubsectionIterator> subsections() const;
bool hasDebugSubsections() const;
@@ -54,7 +61,7 @@ private:
uint32_t Signature;
- std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::shared_ptr<msf::MappedBlockStream> Stream;
codeview::CVSymbolArray SymbolsSubstream;
BinaryStreamRef C11LinesSubstream;
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/include/llvm/DebugInfo/PDB/Native/PDBFile.h
index 3bed67141c56..4d3c569c3cdf 100644
--- a/include/llvm/DebugInfo/PDB/Native/PDBFile.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBFile.h
@@ -108,6 +108,8 @@ public:
bool hasPDBTpiStream() const;
bool hasPDBStringTable();
+ uint32_t getPointerSize();
+
private:
Expected<std::unique_ptr<msf::MappedBlockStream>>
safelyCreateIndexedStream(const msf::MSFLayout &Layout,
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h
index 28a14d7356d2..86ef1136b41d 100644
--- a/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTable.h
@@ -45,7 +45,7 @@ public:
FixedStreamArray<support::ulittle32_t> name_ids() const;
- codeview::DebugStringTableSubsectionRef getStringTable() const;
+ const codeview::DebugStringTableSubsectionRef &getStringTable() const;
private:
Error readHeader(BinaryStreamReader &Reader);
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
index 0faa02dc4525..b57707ee7923 100644
--- a/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h
@@ -41,10 +41,7 @@ public:
uint32_t calculateSerializedSize() const;
Error commit(BinaryStreamWriter &Writer) const;
- codeview::DebugStringTableSubsection &getStrings() { return Strings; }
- const codeview::DebugStringTableSubsection &getStrings() const {
- return Strings;
- }
+ void setStrings(const codeview::DebugStringTableSubsection &Strings);
private:
uint32_t calculateHashTableSize() const;
diff --git a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
index 4a541edd6a7b..4570c80c76d7 100644
--- a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
@@ -35,6 +35,7 @@ public:
uint32_t getSymHash() const;
uint32_t getAddrMap() const;
uint32_t getNumBuckets() const { return NumBuckets; }
+ Expected<const codeview::CVSymbolArray &> getSymbolArray() const;
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
diff --git a/include/llvm/DebugInfo/PDB/Native/RawConstants.h b/include/llvm/DebugInfo/PDB/Native/RawConstants.h
index e1bd86b2870b..bb1d097b5123 100644
--- a/include/llvm/DebugInfo/PDB/Native/RawConstants.h
+++ b/include/llvm/DebugInfo/PDB/Native/RawConstants.h
@@ -98,15 +98,19 @@ enum class DbgHeaderType : uint16_t {
};
enum class OMFSegDescFlags : uint16_t {
+ None = 0,
Read = 1 << 0, // Segment is readable.
Write = 1 << 1, // Segment is writable.
Execute = 1 << 2, // Segment is executable.
AddressIs32Bit = 1 << 3, // Descriptor describes a 32-bit linear address.
IsSelector = 1 << 8, // Frame represents a selector.
IsAbsoluteAddress = 1 << 9, // Frame represents an absolute address.
- IsGroup = 1 << 10 // If set, descriptor represents a group.
+ IsGroup = 1 << 10, // If set, descriptor represents a group.
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ IsGroup)
};
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
} // end namespace pdb
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
index 41d5e6ad64a0..17695f587849 100644
--- a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
@@ -27,6 +27,10 @@ public:
~SymbolStream();
Error reload();
+ const codeview::CVSymbolArray &getSymbolArray() const {
+ return SymbolRecords;
+ }
+
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
diff --git a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
index 21cfa83e6af4..411720d6f56b 100644
--- a/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
@@ -58,6 +58,8 @@ public:
Error finalizeMsfLayout();
+ uint32_t getRecordCount() const { return TypeRecords.size(); }
+
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer);
uint32_t calculateSerializedLength();
diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h
index bb5e1931393b..003a6d5d075d 100644
--- a/include/llvm/IR/Constants.h
+++ b/include/llvm/IR/Constants.h
@@ -68,11 +68,8 @@ protected:
void *operator new(size_t s) { return User::operator new(s, 0); }
public:
- ConstantData() = delete;
ConstantData(const ConstantData &) = delete;
- void *operator new(size_t, unsigned) = delete;
-
/// Methods to support type inquiry through isa, cast, and dyn_cast.
static bool classof(const Value *V) {
return V->getValueID() >= ConstantDataFirstVal &&
@@ -691,8 +688,6 @@ class ConstantDataArray final : public ConstantDataSequential {
public:
ConstantDataArray(const ConstantDataArray &) = delete;
- void *operator new(size_t, unsigned) = delete;
-
/// get() constructors - Return a constant with array type with an element
/// count and element type matching the ArrayRef passed in. Note that this
/// can return a ConstantAggregateZero object.
@@ -752,8 +747,6 @@ class ConstantDataVector final : public ConstantDataSequential {
public:
ConstantDataVector(const ConstantDataVector &) = delete;
- void *operator new(size_t, unsigned) = delete;
-
/// get() constructors - Return a constant with vector type with an element
/// count and element type matching the ArrayRef passed in. Note that this
/// can return a ConstantAggregateZero object.
@@ -830,8 +823,6 @@ class BlockAddress final : public Constant {
Value *handleOperandChangeImpl(Value *From, Value *To);
public:
- void *operator new(size_t, unsigned) = delete;
-
/// Return a BlockAddress for the specified function and basic block.
static BlockAddress *get(Function *F, BasicBlock *BB);
diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h
index 2174e1f301ee..9374fe4fae76 100644
--- a/include/llvm/IR/DebugInfoMetadata.h
+++ b/include/llvm/IR/DebugInfoMetadata.h
@@ -2117,9 +2117,6 @@ public:
/// variable, or the location of a single piece of a variable, or (when using
/// DW_OP_stack_value) is the constant variable value.
///
-/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const
-/// and have DW_OP_plus consume the topmost elements on the stack.
-///
/// TODO: Co-allocate the expression elements.
/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary
/// storage types.
diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h
index 454492769c8b..8255a4f298c0 100644
--- a/include/llvm/IR/GlobalVariable.h
+++ b/include/llvm/IR/GlobalVariable.h
@@ -78,8 +78,6 @@ public:
return User::operator new(s, 1);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Provide fast operand accessors
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h
index 5ddaf2b1733b..ec33f82f7022 100644
--- a/include/llvm/IR/IRBuilder.h
+++ b/include/llvm/IR/IRBuilder.h
@@ -435,27 +435,25 @@ public:
MDNode *ScopeTag = nullptr,
MDNode *NoAliasTag = nullptr);
- /// \brief Create and insert an atomic memcpy between the specified
- /// pointers.
+ /// \brief Create and insert an element unordered-atomic memcpy between the
+ /// specified pointers.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
/// specified, it will be added to the instruction. Likewise with alias.scope
/// and noalias tags.
- CallInst *CreateElementAtomicMemCpy(
- Value *Dst, Value *Src, uint64_t NumElements, uint32_t ElementSize,
+ CallInst *CreateElementUnorderedAtomicMemCpy(
+ Value *Dst, Value *Src, uint64_t Size, uint32_t ElementSize,
MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr) {
- return CreateElementAtomicMemCpy(Dst, Src, getInt64(NumElements),
- ElementSize, TBAATag, TBAAStructTag,
- ScopeTag, NoAliasTag);
+ return CreateElementUnorderedAtomicMemCpy(
+ Dst, Src, getInt64(Size), ElementSize, TBAATag, TBAAStructTag, ScopeTag,
+ NoAliasTag);
}
- CallInst *CreateElementAtomicMemCpy(Value *Dst, Value *Src,
- Value *NumElements, uint32_t ElementSize,
- MDNode *TBAATag = nullptr,
- MDNode *TBAAStructTag = nullptr,
- MDNode *ScopeTag = nullptr,
- MDNode *NoAliasTag = nullptr);
+ CallInst *CreateElementUnorderedAtomicMemCpy(
+ Value *Dst, Value *Src, Value *Size, uint32_t ElementSize,
+ MDNode *TBAATag = nullptr, MDNode *TBAAStructTag = nullptr,
+ MDNode *ScopeTag = nullptr, MDNode *NoAliasTag = nullptr);
/// \brief Create and insert a memmove between the specified
/// pointers.
diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h
index ff63da50afee..b3c6644c7e81 100644
--- a/include/llvm/IR/InstrTypes.h
+++ b/include/llvm/IR/InstrTypes.h
@@ -294,8 +294,6 @@ public:
return User::operator new(s, 1);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -343,8 +341,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
@@ -907,15 +903,11 @@ protected:
BasicBlock *InsertAtEnd);
public:
- CmpInst() = delete;
-
// allocate space for exactly two operands
void *operator new(size_t s) {
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Construct a compare instruction, given the opcode, the predicate and
/// the two operands. Optionally (if InstBefore is specified) insert the
/// instruction into a BasicBlock right before the specified instruction.
diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h
index 6029b0a7c571..b3032f54aa42 100644
--- a/include/llvm/IR/Instructions.h
+++ b/include/llvm/IR/Instructions.h
@@ -337,8 +337,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Return true if this is a store to a volatile memory location.
bool isVolatile() const { return getSubclassDataFromInstruction() & 1; }
@@ -460,8 +458,6 @@ public:
return User::operator new(s, 0);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Returns the ordering effect of this fence.
AtomicOrdering getOrdering() const {
return AtomicOrdering(getSubclassDataFromInstruction() >> 1);
@@ -538,8 +534,6 @@ public:
return User::operator new(s, 3);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Return true if this is a cmpxchg from a volatile memory
/// location.
///
@@ -728,8 +722,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
BinOp getOperation() const {
return static_cast<BinOp>(getSubclassDataFromInstruction() >> 5);
}
@@ -2234,8 +2226,6 @@ public:
return User::operator new(s, 3);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Return true if a shufflevector instruction can be
/// formed with the specified operands.
static bool isValidOperands(const Value *V1, const Value *V2,
@@ -2467,8 +2457,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
static InsertValueInst *Create(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs,
const Twine &NameStr = "",
@@ -2596,11 +2584,6 @@ class PHINode : public Instruction {
allocHungoffUses(ReservedSpace);
}
- // allocate space for exactly zero operands
- void *operator new(size_t s) {
- return User::operator new(s);
- }
-
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
friend class Instruction;
@@ -2615,8 +2598,6 @@ protected:
}
public:
- void *operator new(size_t, unsigned) = delete;
-
/// Constructors - NumReservedValues is a hint for the number of incoming
/// edges that this phi node will have (use 0 if you really have no idea).
static PHINode *Create(Type *Ty, unsigned NumReservedValues,
@@ -2834,8 +2815,6 @@ protected:
LandingPadInst *cloneImpl() const;
public:
- void *operator new(size_t, unsigned) = delete;
-
/// Constructors - NumReservedClauses is a hint for the number of incoming
/// clauses that this landingpad will have (use 0 if you really have no idea).
static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses,
@@ -3134,8 +3113,6 @@ protected:
SwitchInst *cloneImpl() const;
public:
- void *operator new(size_t, unsigned) = delete;
-
// -2
static const unsigned DefaultPseudoIndex = static_cast<unsigned>(~0L-1);
@@ -3489,8 +3466,6 @@ protected:
IndirectBrInst *cloneImpl() const;
public:
- void *operator new(size_t, unsigned) = delete;
-
static IndirectBrInst *Create(Value *Address, unsigned NumDests,
Instruction *InsertBefore = nullptr) {
return new IndirectBrInst(Address, NumDests, InsertBefore);
@@ -4173,8 +4148,6 @@ protected:
CatchSwitchInst *cloneImpl() const;
public:
- void *operator new(size_t, unsigned) = delete;
-
static CatchSwitchInst *Create(Value *ParentPad, BasicBlock *UnwindDest,
unsigned NumHandlers,
const Twine &NameStr = "",
@@ -4609,8 +4582,6 @@ public:
return User::operator new(s, 0);
}
- void *operator new(size_t, unsigned) = delete;
-
unsigned getNumSuccessors() const { return 0; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index 2ae98d9e35b0..e0dd3ca7d01e 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -205,25 +205,91 @@ namespace llvm {
};
/// This class represents atomic memcpy intrinsic
- /// TODO: Integrate this class into MemIntrinsic hierarchy.
- class ElementAtomicMemCpyInst : public IntrinsicInst {
+ /// TODO: Integrate this class into MemIntrinsic hierarchy; for now this is
+ /// C&P of all methods from that hierarchy
+ class ElementUnorderedAtomicMemCpyInst : public IntrinsicInst {
+ private:
+ enum { ARG_DEST = 0, ARG_SOURCE = 1, ARG_LENGTH = 2, ARG_ELEMENTSIZE = 3 };
+
public:
- Value *getRawDest() const { return getArgOperand(0); }
- Value *getRawSource() const { return getArgOperand(1); }
+ Value *getRawDest() const {
+ return const_cast<Value *>(getArgOperand(ARG_DEST));
+ }
+ const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); }
+ Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); }
+
+ /// Return the arguments to the instruction.
+ Value *getRawSource() const {
+ return const_cast<Value *>(getArgOperand(ARG_SOURCE));
+ }
+ const Use &getRawSourceUse() const { return getArgOperandUse(ARG_SOURCE); }
+ Use &getRawSourceUse() { return getArgOperandUse(ARG_SOURCE); }
+
+ Value *getLength() const {
+ return const_cast<Value *>(getArgOperand(ARG_LENGTH));
+ }
+ const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); }
+ Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); }
+
+ bool isVolatile() const { return false; }
+
+ Value *getRawElementSizeInBytes() const {
+ return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE));
+ }
+
+ ConstantInt *getElementSizeInBytesCst() const {
+ return cast<ConstantInt>(getRawElementSizeInBytes());
+ }
+
+ uint32_t getElementSizeInBytes() const {
+ return getElementSizeInBytesCst()->getZExtValue();
+ }
+
+ /// This is just like getRawDest, but it strips off any cast
+ /// instructions that feed it, giving the original input. The returned
+ /// value is guaranteed to be a pointer.
+ Value *getDest() const { return getRawDest()->stripPointerCasts(); }
+
+ /// This is just like getRawSource, but it strips off any cast
+ /// instructions that feed it, giving the original input. The returned
+ /// value is guaranteed to be a pointer.
+ Value *getSource() const { return getRawSource()->stripPointerCasts(); }
+
+ unsigned getDestAddressSpace() const {
+ return cast<PointerType>(getRawDest()->getType())->getAddressSpace();
+ }
- Value *getNumElements() const { return getArgOperand(2); }
- void setNumElements(Value *V) { setArgOperand(2, V); }
+ unsigned getSourceAddressSpace() const {
+ return cast<PointerType>(getRawSource()->getType())->getAddressSpace();
+ }
- uint64_t getSrcAlignment() const { return getParamAlignment(0); }
- uint64_t getDstAlignment() const { return getParamAlignment(1); }
+ /// Set the specified arguments of the instruction.
+ void setDest(Value *Ptr) {
+ assert(getRawDest()->getType() == Ptr->getType() &&
+ "setDest called with pointer of wrong type!");
+ setArgOperand(ARG_DEST, Ptr);
+ }
+
+ void setSource(Value *Ptr) {
+ assert(getRawSource()->getType() == Ptr->getType() &&
+ "setSource called with pointer of wrong type!");
+ setArgOperand(ARG_SOURCE, Ptr);
+ }
+
+ void setLength(Value *L) {
+ assert(getLength()->getType() == L->getType() &&
+ "setLength called with value of wrong type!");
+ setArgOperand(ARG_LENGTH, L);
+ }
- uint64_t getElementSizeInBytes() const {
- Value *Arg = getArgOperand(3);
- return cast<ConstantInt>(Arg)->getZExtValue();
+ void setElementSizeInBytes(Constant *V) {
+ assert(V->getType() == Type::getInt8Ty(getContext()) &&
+ "setElementSizeInBytes called with value of wrong type!");
+ setArgOperand(ARG_ELEMENTSIZE, V);
}
static inline bool classof(const IntrinsicInst *I) {
- return I->getIntrinsicID() == Intrinsic::memcpy_element_atomic;
+ return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic;
}
static inline bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index 291d16fb0d9b..45936a6e9b66 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -862,11 +862,16 @@ def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty],
//===------ Memory intrinsics with element-wise atomicity guarantees ------===//
//
-def int_memcpy_element_atomic : Intrinsic<[],
- [llvm_anyptr_ty, llvm_anyptr_ty,
- llvm_i64_ty, llvm_i32_ty],
- [IntrArgMemOnly, NoCapture<0>, NoCapture<1>,
- WriteOnly<0>, ReadOnly<1>]>;
+// @llvm.memcpy.element.unordered.atomic.*(dest, src, length, elementsize)
+def int_memcpy_element_unordered_atomic
+ : Intrinsic<[],
+ [
+ llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty
+ ],
+ [
+ IntrArgMemOnly, NoCapture<0>, NoCapture<1>, WriteOnly<0>,
+ ReadOnly<1>
+ ]>;
//===------------------------ Reduction Intrinsics ------------------------===//
//
diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h
index 144e45f18d2c..b43d58865862 100644
--- a/include/llvm/IR/ModuleSummaryIndex.h
+++ b/include/llvm/IR/ModuleSummaryIndex.h
@@ -32,6 +32,7 @@
#include <cstdint>
#include <map>
#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -542,6 +543,9 @@ private:
/// considered live.
bool WithGlobalValueDeadStripping = false;
+ std::set<std::string> CfiFunctionDefs;
+ std::set<std::string> CfiFunctionDecls;
+
// YAML I/O support.
friend yaml::MappingTraits<ModuleSummaryIndex>;
@@ -567,6 +571,7 @@ public:
bool isGlobalValueLive(const GlobalValueSummary *GVS) const {
return !WithGlobalValueDeadStripping || GVS->isLive();
}
+ bool isGUIDLive(GlobalValue::GUID GUID) const;
/// Return a ValueInfo for GUID if it exists, otherwise return ValueInfo().
ValueInfo getValueInfo(GlobalValue::GUID GUID) const {
@@ -592,6 +597,12 @@ public:
return I == OidGuidMap.end() ? 0 : I->second;
}
+ std::set<std::string> &cfiFunctionDefs() { return CfiFunctionDefs; }
+ const std::set<std::string> &cfiFunctionDefs() const { return CfiFunctionDefs; }
+
+ std::set<std::string> &cfiFunctionDecls() { return CfiFunctionDecls; }
+ const std::set<std::string> &cfiFunctionDecls() const { return CfiFunctionDecls; }
+
/// Add a global value summary for a value of the given name.
void addGlobalValueSummary(StringRef ValueName,
std::unique_ptr<GlobalValueSummary> Summary) {
@@ -691,14 +702,13 @@ public:
return Pair.first;
}
- /// Add a new module path with the given \p Hash, mapped to the given \p
- /// ModID, and return an iterator to the entry in the index.
- ModulePathStringTableTy::iterator
- addModulePath(StringRef ModPath, uint64_t ModId,
- ModuleHash Hash = ModuleHash{{0}}) {
- return ModulePathStringTable.insert(std::make_pair(
- ModPath,
- std::make_pair(ModId, Hash))).first;
+ typedef ModulePathStringTableTy::value_type ModuleInfo;
+
+ /// Add a new module with the given \p Hash, mapped to the given \p
+ /// ModID, and return a reference to the module.
+ ModuleInfo *addModule(StringRef ModPath, uint64_t ModId,
+ ModuleHash Hash = ModuleHash{{0}}) {
+ return &*ModulePathStringTable.insert({ModPath, {ModId, Hash}}).first;
}
/// Check if the given Module has any functions available for exporting
diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h
index 891d84c2dbca..8950c527cc18 100644
--- a/include/llvm/IR/ModuleSummaryIndexYAML.h
+++ b/include/llvm/IR/ModuleSummaryIndexYAML.h
@@ -188,6 +188,7 @@ template <> struct MappingTraits<FunctionSummaryYaml> {
LLVM_YAML_IS_STRING_MAP(TypeIdSummary)
LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionSummaryYaml)
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)
namespace llvm {
namespace yaml {
@@ -240,6 +241,23 @@ template <> struct MappingTraits<ModuleSummaryIndex> {
io.mapOptional("TypeIdMap", index.TypeIdMap);
io.mapOptional("WithGlobalValueDeadStripping",
index.WithGlobalValueDeadStripping);
+
+ if (io.outputting()) {
+ std::vector<std::string> CfiFunctionDefs(index.CfiFunctionDefs.begin(),
+ index.CfiFunctionDefs.end());
+ io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
+ std::vector<std::string> CfiFunctionDecls(index.CfiFunctionDecls.begin(),
+ index.CfiFunctionDecls.end());
+ io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
+ } else {
+ std::vector<std::string> CfiFunctionDefs;
+ io.mapOptional("CfiFunctionDefs", CfiFunctionDefs);
+ index.CfiFunctionDefs = {CfiFunctionDefs.begin(), CfiFunctionDefs.end()};
+ std::vector<std::string> CfiFunctionDecls;
+ io.mapOptional("CfiFunctionDecls", CfiFunctionDecls);
+ index.CfiFunctionDecls = {CfiFunctionDecls.begin(),
+ CfiFunctionDecls.end()};
+ }
}
};
diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h
index 49fa6a6a877a..6eb5998478c6 100644
--- a/include/llvm/IR/Operator.h
+++ b/include/llvm/IR/Operator.h
@@ -35,7 +35,6 @@ public:
Operator() = delete;
~Operator() = delete;
- void *operator new(size_t, unsigned) = delete;
void *operator new(size_t s) = delete;
/// Return the opcode for this Instruction or ConstantExpr.
diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h
index 542570aaaa24..015a17e8e7ca 100644
--- a/include/llvm/IR/PatternMatch.h
+++ b/include/llvm/IR/PatternMatch.h
@@ -1027,7 +1027,7 @@ struct MaxMin_match {
(TrueVal != RHS || FalseVal != LHS))
return false;
typename CmpInst_t::Predicate Pred =
- LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate();
+ LHS == TrueVal ? Cmp->getPredicate() : Cmp->getInversePredicate();
// Does "(x pred y) ? x : y" represent the desired max/min operation?
if (!Pred_t::match(Pred))
return false;
@@ -1138,7 +1138,7 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmax_pred_ty> m_OrdFMax(const LHS &L,
/// semantics. In the presence of 'NaN' we have to preserve the original
/// select(fcmp(olt/le, L, R), L, R) semantics matched by this predicate.
///
-/// max(L, R) iff L and R are not NaN
+/// min(L, R) iff L and R are not NaN
/// m_OrdFMin(L, R) = R iff L or R are NaN
template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
@@ -1154,13 +1154,28 @@ inline MaxMin_match<FCmpInst, LHS, RHS, ofmin_pred_ty> m_OrdFMin(const LHS &L,
/// select(fcmp(ugt/ge, L, R), L, R) semantics matched by this predicate.
///
/// max(L, R) iff L and R are not NaN
-/// m_UnordFMin(L, R) = L iff L or R are NaN
+/// m_UnordFMax(L, R) = L iff L or R are NaN
template <typename LHS, typename RHS>
inline MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>
m_UnordFMax(const LHS &L, const RHS &R) {
return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R);
}
+/// \brief Match an 'unordered' floating point minimum function.
+/// Floating point has one special value 'NaN'. Therefore, there is no total
+/// order. However, if we can ignore the 'NaN' value (for example, because of a
+/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum'
+/// semantics. In the presence of 'NaN' we have to preserve the original
+/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate.
+///
+/// min(L, R) iff L and R are not NaN
+/// m_UnordFMin(L, R) = L iff L or R are NaN
+template <typename LHS, typename RHS>
+inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>
+m_UnordFMin(const LHS &L, const RHS &R) {
+ return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
+}
+
//===----------------------------------------------------------------------===//
// Matchers for overflow check patterns: e.g. (a + b) u< a
//
@@ -1207,21 +1222,6 @@ m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) {
return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S);
}
-/// \brief Match an 'unordered' floating point minimum function.
-/// Floating point has one special value 'NaN'. Therefore, there is no total
-/// order. However, if we can ignore the 'NaN' value (for example, because of a
-/// 'no-nans-float-math' flag) a combination of a fcmp and select has 'minimum'
-/// semantics. In the presence of 'NaN' we have to preserve the original
-/// select(fcmp(ult/le, L, R), L, R) semantics matched by this predicate.
-///
-/// max(L, R) iff L and R are not NaN
-/// m_UnordFMin(L, R) = L iff L or R are NaN
-template <typename LHS, typename RHS>
-inline MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>
-m_UnordFMin(const LHS &L, const RHS &R) {
- return MaxMin_match<FCmpInst, LHS, RHS, ufmin_pred_ty>(L, R);
-}
-
template <typename Opnd_t> struct Argument_match {
unsigned OpI;
Opnd_t Val;
diff --git a/include/llvm/LTO/LTO.h b/include/llvm/LTO/LTO.h
index 774e144b3ef0..d678a68ed860 100644
--- a/include/llvm/LTO/LTO.h
+++ b/include/llvm/LTO/LTO.h
@@ -281,6 +281,16 @@ private:
bool HasModule = false;
std::unique_ptr<Module> CombinedModule;
std::unique_ptr<IRMover> Mover;
+
+ // This stores the information about a regular LTO module that we have added
+ // to the link. It will either be linked immediately (for modules without
+ // summaries) or after summary-based dead stripping (for modules with
+ // summaries).
+ struct AddedModule {
+ std::unique_ptr<Module> M;
+ std::vector<GlobalValue *> Keep;
+ };
+ std::vector<AddedModule> ModsWithSummaries;
} RegularLTO;
struct ThinLTOState {
@@ -303,9 +313,10 @@ private:
/// The unmangled name of the global.
std::string IRName;
- /// Keep track if the symbol is visible outside of ThinLTO (i.e. in
- /// either a regular object or the regular LTO partition).
- bool VisibleOutsideThinLTO = false;
+ /// Keep track if the symbol is visible outside of a module with a summary
+ /// (i.e. in either a regular object or a regular LTO module without a
+ /// summary).
+ bool VisibleOutsideSummary = false;
bool UnnamedAddr = true;
@@ -339,8 +350,9 @@ private:
// Global mapping from mangled symbol names to resolutions.
StringMap<GlobalResolution> GlobalResolutions;
- void addSymbolToGlobalRes(const InputFile::Symbol &Sym, SymbolResolution Res,
- unsigned Partition);
+ void addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
+ ArrayRef<SymbolResolution> Res, unsigned Partition,
+ bool InSummary);
// These functions take a range of symbol resolutions [ResI, ResE) and consume
// the resolutions used by a single input module by incrementing ResI. After
@@ -348,10 +360,13 @@ private:
// the remaining modules in the InputFile.
Error addModule(InputFile &Input, unsigned ModI,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
- Error addRegularLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
- const SymbolResolution *&ResI,
- const SymbolResolution *ResE);
+
+ Expected<RegularLTOState::AddedModule>
+ addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
+ const SymbolResolution *&ResI, const SymbolResolution *ResE);
+ Error linkRegularLTO(RegularLTOState::AddedModule Mod,
+ bool LivenessFromIndex);
+
Error addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI, const SymbolResolution *ResE);
diff --git a/include/llvm/LTO/legacy/LTOModule.h b/include/llvm/LTO/legacy/LTOModule.h
index 2a8758587a11..017e223ed8a6 100644
--- a/include/llvm/LTO/legacy/LTOModule.h
+++ b/include/llvm/LTO/legacy/LTOModule.h
@@ -158,7 +158,7 @@ public:
private:
/// Parse metadata from the module
- // FIXME: it only parses "Linker Options" metadata at the moment
+ // FIXME: it only parses "llvm.linker.options" metadata at the moment
void parseMetadata();
/// Parse the symbols from the module and model-level ASM and add them to
diff --git a/include/llvm/MC/MCSymbolWasm.h b/include/llvm/MC/MCSymbolWasm.h
index 7d661ccc5de7..1b87095552d6 100644
--- a/include/llvm/MC/MCSymbolWasm.h
+++ b/include/llvm/MC/MCSymbolWasm.h
@@ -13,6 +13,7 @@
#include "llvm/MC/MCSymbol.h"
namespace llvm {
+
class MCSymbolWasm : public MCSymbol {
private:
bool IsFunction = false;
@@ -52,6 +53,7 @@ public:
Params = std::move(Pars);
}
};
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_MC_MCSYMBOLWASM_H
diff --git a/include/llvm/MC/MCWasmObjectWriter.h b/include/llvm/MC/MCWasmObjectWriter.h
index c250d3bf03fb..bebc0a825810 100644
--- a/include/llvm/MC/MCWasmObjectWriter.h
+++ b/include/llvm/MC/MCWasmObjectWriter.h
@@ -12,20 +12,12 @@
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Wasm.h"
-#include "llvm/MC/MCValue.h"
#include "llvm/Support/DataTypes.h"
-#include "llvm/Support/raw_ostream.h"
-#include <vector>
namespace llvm {
-class MCAssembler;
-class MCContext;
+
class MCFixup;
-class MCFragment;
class MCObjectWriter;
-class MCSectionWasm;
-class MCSymbol;
-class MCSymbolWasm;
class MCValue;
class raw_pwrite_stream;
@@ -38,8 +30,8 @@ protected:
public:
virtual ~MCWasmObjectTargetWriter();
- virtual unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
- const MCFixup &Fixup, bool IsPCRel) const = 0;
+ virtual unsigned getRelocType(const MCValue &Target,
+ const MCFixup &Fixup) const = 0;
/// \name Accessors
/// @{
@@ -54,6 +46,7 @@ public:
/// \returns The constructed object writer.
MCObjectWriter *createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
raw_pwrite_stream &OS);
+
} // End llvm namespace
#endif
diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h
index 3e84a5814d79..1ed758d40df2 100644
--- a/include/llvm/Object/ArchiveWriter.h
+++ b/include/llvm/Object/ArchiveWriter.h
@@ -22,6 +22,7 @@ namespace llvm {
struct NewArchiveMember {
std::unique_ptr<MemoryBuffer> Buf;
+ StringRef MemberName;
sys::TimePoint<std::chrono::seconds> ModTime;
unsigned UID = 0, GID = 0, Perms = 0644;
diff --git a/include/llvm/Object/WindowsResource.h b/include/llvm/Object/WindowsResource.h
index c5189329d3ec..4839013c8228 100644
--- a/include/llvm/Object/WindowsResource.h
+++ b/include/llvm/Object/WindowsResource.h
@@ -118,7 +118,7 @@ public:
class TreeNode;
WindowsResourceParser();
Error parse(WindowsResource *WR);
- void printTree() const;
+ void printTree(raw_ostream &OS) const;
const TreeNode &getTree() const { return Root; }
const ArrayRef<std::vector<uint8_t>> getData() const { return Data; }
const ArrayRef<std::vector<UTF16>> getStringTable() const {
@@ -159,14 +159,16 @@ public:
TreeNode(uint16_t MajorVersion, uint16_t MinorVersion,
uint32_t Characteristics);
- void addEntry(const ResourceEntryRef &Entry);
- TreeNode &addTypeNode(const ResourceEntryRef &Entry);
- TreeNode &addNameNode(const ResourceEntryRef &Entry);
+ void addEntry(const ResourceEntryRef &Entry, bool &IsNewTypeString,
+ bool &IsNewNameString);
+ TreeNode &addTypeNode(const ResourceEntryRef &Entry, bool &IsNewTypeString);
+ TreeNode &addNameNode(const ResourceEntryRef &Entry, bool &IsNewNameString);
TreeNode &addLanguageNode(const ResourceEntryRef &Entry);
TreeNode &addChild(uint32_t ID, bool IsDataNode = false,
uint16_t MajorVersion = 0, uint16_t MinorVersion = 0,
uint32_t Characteristics = 0);
- TreeNode &addChild(ArrayRef<UTF16> NameRef);
+ TreeNode &addChild(ArrayRef<UTF16> NameRef, bool &IsNewString);
+
bool IsDataNode = false;
uint32_t StringIndex;
uint32_t DataIndex;
diff --git a/include/llvm/ObjectYAML/COFFYAML.h b/include/llvm/ObjectYAML/COFFYAML.h
index 1b5f7b00239a..719cb1acf6ef 100644
--- a/include/llvm/ObjectYAML/COFFYAML.h
+++ b/include/llvm/ObjectYAML/COFFYAML.h
@@ -16,6 +16,8 @@
#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h"
+#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
#include "llvm/ObjectYAML/YAML.h"
namespace llvm {
@@ -56,6 +58,8 @@ namespace COFFYAML {
COFF::section Header;
unsigned Alignment = 0;
yaml::BinaryRef SectionData;
+ std::vector<CodeViewYAML::YAMLDebugSubsection> DebugS;
+ std::vector<CodeViewYAML::LeafRecord> DebugT;
std::vector<Relocation> Relocations;
StringRef Name;
Section();
diff --git a/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h
index faa3ed8a6c52..8180e0fc83f4 100644
--- a/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h
+++ b/include/llvm/ObjectYAML/CodeViewYAMLDebugSections.h
@@ -28,6 +28,8 @@ class DebugStringTableSubsectionRef;
class DebugChecksumsSubsectionRef;
class DebugStringTableSubsection;
class DebugChecksumsSubsection;
+class StringsAndChecksums;
+class StringsAndChecksumsRef;
}
namespace CodeViewYAML {
@@ -103,25 +105,24 @@ struct InlineeInfo {
struct YAMLDebugSubsection {
static Expected<YAMLDebugSubsection>
- fromCodeViewSubection(const codeview::DebugStringTableSubsectionRef &Strings,
- const codeview::DebugChecksumsSubsectionRef &Checksums,
+ fromCodeViewSubection(const codeview::StringsAndChecksumsRef &SC,
const codeview::DebugSubsectionRecord &SS);
std::shared_ptr<detail::YAMLSubsectionBase> Subsection;
};
-Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
+struct DebugSubsectionState {};
+
+Expected<std::vector<std::shared_ptr<codeview::DebugSubsection>>>
toCodeViewSubsectionList(BumpPtrAllocator &Allocator,
ArrayRef<YAMLDebugSubsection> Subsections,
- codeview::DebugStringTableSubsection &Strings);
-Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
-toCodeViewSubsectionList(
- BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
- std::unique_ptr<codeview::DebugStringTableSubsection> &TakeStrings,
- codeview::DebugStringTableSubsection *StringsRef);
-
-std::unique_ptr<codeview::DebugStringTableSubsection>
-findStringTable(ArrayRef<YAMLDebugSubsection> Sections);
+ const codeview::StringsAndChecksums &SC);
+
+std::vector<YAMLDebugSubsection>
+fromDebugS(ArrayRef<uint8_t> Data, const codeview::StringsAndChecksumsRef &SC);
+
+void initializeStringsAndChecksums(ArrayRef<YAMLDebugSubsection> Sections,
+ codeview::StringsAndChecksums &SC);
} // namespace CodeViewYAML
} // namespace llvm
diff --git a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
index 91b75aabe7a5..e97d5f92bf7f 100644
--- a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
+++ b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h
@@ -41,6 +41,9 @@ struct LeafRecord {
codeview::CVType toCodeViewRecord(codeview::TypeTableBuilder &TS) const;
static Expected<LeafRecord> fromCodeViewRecord(codeview::CVType Type);
};
+
+std::vector<LeafRecord> fromDebugT(ArrayRef<uint8_t> DebugT);
+ArrayRef<uint8_t> toDebugT(ArrayRef<LeafRecord>, BumpPtrAllocator &Alloc);
} // namespace CodeViewYAML
} // namespace llvm
diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h
index 99d329693de2..c519a4a824c5 100644
--- a/include/llvm/Option/Arg.h
+++ b/include/llvm/Option/Arg.h
@@ -1,4 +1,4 @@
-//===--- Arg.h - Parsed Argument Classes ------------------------*- C++ -*-===//
+//===- Arg.h - Parsed Argument Classes --------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,7 +21,11 @@
#include <string>
namespace llvm {
+
+class raw_ostream;
+
namespace opt {
+
class ArgList;
/// \brief A concrete instance of a particular driver option.
@@ -29,9 +33,6 @@ class ArgList;
/// The Arg class encodes just enough information to be able to
/// derive the argument values efficiently.
class Arg {
- Arg(const Arg &) = delete;
- void operator=(const Arg &) = delete;
-
private:
/// \brief The option this argument is an instance of.
const Option Opt;
@@ -65,6 +66,8 @@ public:
const char *Value0, const Arg *BaseArg = nullptr);
Arg(const Option Opt, StringRef Spelling, unsigned Index,
const char *Value0, const char *Value1, const Arg *BaseArg = nullptr);
+ Arg(const Arg &) = delete;
+ Arg &operator=(const Arg &) = delete;
~Arg();
const Option &getOption() const { return Opt; }
@@ -89,6 +92,7 @@ public:
void claim() const { getBaseArg().Claimed = true; }
unsigned getNumValues() const { return Values.size(); }
+
const char *getValue(unsigned N = 0) const {
return Values[N];
}
@@ -122,6 +126,7 @@ public:
};
} // end namespace opt
+
} // end namespace llvm
-#endif
+#endif // LLVM_OPTION_ARG_H
diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h
index 6a92dd01e911..aaea68bf8e27 100644
--- a/include/llvm/Option/ArgList.h
+++ b/include/llvm/Option/ArgList.h
@@ -1,4 +1,4 @@
-//===--- ArgList.h - Argument List Management -------------------*- C++ -*-===//
+//===- ArgList.h - Argument List Management ---------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,7 +10,9 @@
#ifndef LLVM_OPTION_ARGLIST_H
#define LLVM_OPTION_ARGLIST_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -18,15 +20,21 @@
#include "llvm/Option/Arg.h"
#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/Option.h"
+#include <algorithm>
+#include <cstddef>
+#include <initializer_list>
+#include <iterator>
#include <list>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
namespace llvm {
+
+class raw_ostream;
+
namespace opt {
-class ArgList;
-class Option;
/// arg_iterator - Iterates through arguments stored inside an ArgList.
template<typename BaseIter, unsigned NumOptSpecifiers = 0>
@@ -59,14 +67,14 @@ class arg_iterator {
}
}
- typedef std::iterator_traits<BaseIter> Traits;
+ using Traits = std::iterator_traits<BaseIter>;
public:
- typedef typename Traits::value_type value_type;
- typedef typename Traits::reference reference;
- typedef typename Traits::pointer pointer;
- typedef std::forward_iterator_tag iterator_category;
- typedef std::ptrdiff_t difference_type;
+ using value_type = typename Traits::value_type;
+ using reference = typename Traits::reference;
+ using pointer = typename Traits::pointer;
+ using iterator_category = std::forward_iterator_tag;
+ using difference_type = std::ptrdiff_t;
arg_iterator(
BaseIter Current, BaseIter End,
@@ -111,12 +119,12 @@ public:
/// and to iterate over groups of arguments.
class ArgList {
public:
- typedef SmallVector<Arg*, 16> arglist_type;
- typedef arg_iterator<arglist_type::iterator> iterator;
- typedef arg_iterator<arglist_type::const_iterator> const_iterator;
- typedef arg_iterator<arglist_type::reverse_iterator> reverse_iterator;
- typedef arg_iterator<arglist_type::const_reverse_iterator>
- const_reverse_iterator;
+ using arglist_type = SmallVector<Arg *, 16>;
+ using iterator = arg_iterator<arglist_type::iterator>;
+ using const_iterator = arg_iterator<arglist_type::const_iterator>;
+ using reverse_iterator = arg_iterator<arglist_type::reverse_iterator>;
+ using const_reverse_iterator =
+ arg_iterator<arglist_type::const_reverse_iterator>;
template<unsigned N> using filtered_iterator =
arg_iterator<arglist_type::const_iterator, N>;
@@ -127,7 +135,7 @@ private:
/// The internal list of arguments.
arglist_type Args;
- typedef std::pair<unsigned, unsigned> OptRange;
+ using OptRange = std::pair<unsigned, unsigned>;
static OptRange emptyRange() { return {-1u, 0u}; }
/// The first and last index of each different OptSpecifier ID.
@@ -142,6 +150,7 @@ protected:
// derived objects, but can still be used by derived objects to implement
// their own special members.
ArgList() = default;
+
// Explicit move operations to ensure the container is cleared post-move
// otherwise it could lead to a double-delete in the case of moving of an
// InputArgList which deletes the contents of the container. If we could fix
@@ -152,6 +161,7 @@ protected:
RHS.Args.clear();
RHS.OptRanges.clear();
}
+
ArgList &operator=(ArgList &&RHS) {
Args = std::move(RHS.Args);
RHS.Args.clear();
@@ -159,6 +169,7 @@ protected:
RHS.OptRanges.clear();
return *this;
}
+
// Protect the dtor to ensure this type is never destroyed polymorphically.
~ArgList() = default;
@@ -380,10 +391,12 @@ private:
public:
InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
+
InputArgList(InputArgList &&RHS)
: ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)),
SynthesizedStrings(std::move(RHS.SynthesizedStrings)),
NumInputArgStrings(RHS.NumInputArgStrings) {}
+
InputArgList &operator=(InputArgList &&RHS) {
releaseMemory();
ArgList::operator=(std::move(RHS));
@@ -392,6 +405,7 @@ public:
NumInputArgStrings = RHS.NumInputArgStrings;
return *this;
}
+
~InputArgList() { releaseMemory(); }
const char *getArgString(unsigned Index) const override {
@@ -464,7 +478,6 @@ public:
append(MakePositionalArg(BaseArg, Opt, Value));
}
-
/// AddSeparateArg - Construct a new Positional arg for the given option
/// \p Id, with the provided \p Value and append it to the argument
/// list.
@@ -473,7 +486,6 @@ public:
append(MakeSeparateArg(BaseArg, Opt, Value));
}
-
/// AddJoinedArg - Construct a new Positional arg for the given option
/// \p Id, with the provided \p Value and append it to the argument list.
void AddJoinedArg(const Arg *BaseArg, const Option Opt,
@@ -481,7 +493,6 @@ public:
append(MakeJoinedArg(BaseArg, Opt, Value));
}
-
/// MakeFlagArg - Construct a new FlagArg for the given option \p Id.
Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const;
@@ -504,6 +515,7 @@ public:
};
} // end namespace opt
+
} // end namespace llvm
-#endif
+#endif // LLVM_OPTION_ARGLIST_H
diff --git a/include/llvm/Option/OptSpecifier.h b/include/llvm/Option/OptSpecifier.h
index 0b2aaaec3afc..84c3cf8ad534 100644
--- a/include/llvm/Option/OptSpecifier.h
+++ b/include/llvm/Option/OptSpecifier.h
@@ -1,4 +1,4 @@
-//===--- OptSpecifier.h - Option Specifiers ---------------------*- C++ -*-===//
+//===- OptSpecifier.h - Option Specifiers -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -10,32 +10,30 @@
#ifndef LLVM_OPTION_OPTSPECIFIER_H
#define LLVM_OPTION_OPTSPECIFIER_H
-#include "llvm/Support/Compiler.h"
-
namespace llvm {
namespace opt {
- class Option;
- /// OptSpecifier - Wrapper class for abstracting references to option IDs.
- class OptSpecifier {
- unsigned ID;
+class Option;
+
+/// OptSpecifier - Wrapper class for abstracting references to option IDs.
+class OptSpecifier {
+ unsigned ID = 0;
- private:
- explicit OptSpecifier(bool) = delete;
+public:
+ OptSpecifier() = default;
+ explicit OptSpecifier(bool) = delete;
+ /*implicit*/ OptSpecifier(unsigned ID) : ID(ID) {}
+ /*implicit*/ OptSpecifier(const Option *Opt);
- public:
- OptSpecifier() : ID(0) {}
- /*implicit*/ OptSpecifier(unsigned ID) : ID(ID) {}
- /*implicit*/ OptSpecifier(const Option *Opt);
+ bool isValid() const { return ID != 0; }
- bool isValid() const { return ID != 0; }
+ unsigned getID() const { return ID; }
- unsigned getID() const { return ID; }
+ bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); }
+ bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); }
+};
- bool operator==(OptSpecifier Opt) const { return ID == Opt.getID(); }
- bool operator!=(OptSpecifier Opt) const { return !(*this == Opt); }
- };
-}
-}
+} // end namespace opt
+} // end namespace llvm
-#endif
+#endif // LLVM_OPTION_OPTSPECIFIER_H
diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h
index 8a323a255ca1..e0169b927319 100644
--- a/include/llvm/Option/OptTable.h
+++ b/include/llvm/Option/OptTable.h
@@ -1,4 +1,4 @@
-//===--- OptTable.h - Option Table ------------------------------*- C++ -*-===//
+//===- OptTable.h - Option Table --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,12 +11,19 @@
#define LLVM_OPTION_OPTTABLE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Option/OptSpecifier.h"
+#include <cassert>
+#include <string>
+#include <vector>
namespace llvm {
+
class raw_ostream;
+
namespace opt {
+
class Arg;
class ArgList;
class InputArgList;
@@ -53,12 +60,12 @@ private:
ArrayRef<Info> OptionInfos;
bool IgnoreCase;
- unsigned TheInputOptionID;
- unsigned TheUnknownOptionID;
+ unsigned TheInputOptionID = 0;
+ unsigned TheUnknownOptionID = 0;
/// The index of the first option which can be parsed (i.e., is not a
/// special option like 'input' or 'unknown', and is not an option group).
- unsigned FirstSearchableIndex;
+ unsigned FirstSearchableIndex = 0;
/// The union of all option prefixes. If an argument does not begin with
/// one of these, it is an input.
@@ -176,7 +183,9 @@ public:
void PrintHelp(raw_ostream &OS, const char *Name,
const char *Title, bool ShowHidden = false) const;
};
+
} // end namespace opt
+
} // end namespace llvm
-#endif
+#endif // LLVM_OPTION_OPTTABLE_H
diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h
index 139f281b3c4c..c08834f90598 100644
--- a/include/llvm/Option/Option.h
+++ b/include/llvm/Option/Option.h
@@ -1,4 +1,4 @@
-//===--- Option.h - Abstract Driver Options ---------------------*- C++ -*-===//
+//===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,15 +12,23 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Support/ErrorHandling.h"
+#include <cassert>
+#include <string>
namespace llvm {
+
+class raw_ostream;
+
namespace opt {
+
class Arg;
class ArgList;
+
/// ArgStringList - Type used for constructing argv lists for subprocesses.
-typedef SmallVector<const char*, 16> ArgStringList;
+using ArgStringList = SmallVector<const char *, 16>;
/// Base flags for all options. Custom flags may be added after.
enum DriverFlag {
@@ -202,6 +210,7 @@ public:
};
} // end namespace opt
+
} // end namespace llvm
-#endif
+#endif // LLVM_OPTION_OPTION_H
diff --git a/include/llvm/Support/BinaryStreamArray.h b/include/llvm/Support/BinaryStreamArray.h
index 65ec15f6d9e0..3f5562ba7519 100644
--- a/include/llvm/Support/BinaryStreamArray.h
+++ b/include/llvm/Support/BinaryStreamArray.h
@@ -290,6 +290,12 @@ public:
return FixedStreamArrayIterator<T>(*this, size());
}
+ const T &front() const { return *begin(); }
+ const T &back() const {
+ FixedStreamArrayIterator<T> I = end();
+ return *(--I);
+ }
+
BinaryStreamRef getUnderlyingStream() const { return Stream; }
private:
diff --git a/include/llvm/Support/DebugCounter.h b/include/llvm/Support/DebugCounter.h
index 9687cb7b9d95..a533feae7fa3 100644
--- a/include/llvm/Support/DebugCounter.h
+++ b/include/llvm/Support/DebugCounter.h
@@ -121,10 +121,10 @@ public:
Us.Counters[ID] = Val;
}
- // Dump or print the current counter set.
- LLVM_DUMP_METHOD void dump() { print(dbgs()); }
+ // Dump or print the current counter set into llvm::dbgs().
+ LLVM_DUMP_METHOD void dump() const;
- void print(raw_ostream &OS);
+ void print(raw_ostream &OS) const;
// Get the counter ID for a given named counter, or return 0 if none is found.
unsigned getCounterId(const std::string &Name) const {
diff --git a/include/llvm/Support/FormatAdapters.h b/include/llvm/Support/FormatAdapters.h
index 698e134b328d..197beb7363df 100644
--- a/include/llvm/Support/FormatAdapters.h
+++ b/include/llvm/Support/FormatAdapters.h
@@ -28,14 +28,16 @@ namespace detail {
template <typename T> class AlignAdapter final : public FormatAdapter<T> {
AlignStyle Where;
size_t Amount;
+ char Fill;
public:
- AlignAdapter(T &&Item, AlignStyle Where, size_t Amount)
- : FormatAdapter<T>(std::forward<T>(Item)), Where(Where), Amount(Amount) {}
+ AlignAdapter(T &&Item, AlignStyle Where, size_t Amount, char Fill)
+ : FormatAdapter<T>(std::forward<T>(Item)), Where(Where), Amount(Amount),
+ Fill(Fill) {}
void format(llvm::raw_ostream &Stream, StringRef Style) {
auto Adapter = detail::build_format_adapter(std::forward<T>(this->Item));
- FmtAlign(Adapter, Where, Amount).format(Stream, Style);
+ FmtAlign(Adapter, Where, Amount, Fill).format(Stream, Style);
}
};
@@ -72,8 +74,9 @@ public:
}
template <typename T>
-detail::AlignAdapter<T> fmt_align(T &&Item, AlignStyle Where, size_t Amount) {
- return detail::AlignAdapter<T>(std::forward<T>(Item), Where, Amount);
+detail::AlignAdapter<T> fmt_align(T &&Item, AlignStyle Where, size_t Amount,
+ char Fill = ' ') {
+ return detail::AlignAdapter<T>(std::forward<T>(Item), Where, Amount, Fill);
}
template <typename T>
diff --git a/include/llvm/Support/FormatCommon.h b/include/llvm/Support/FormatCommon.h
index a8c5fdeb6bff..36fbad296c3f 100644
--- a/include/llvm/Support/FormatCommon.h
+++ b/include/llvm/Support/FormatCommon.h
@@ -21,9 +21,11 @@ struct FmtAlign {
detail::format_adapter &Adapter;
AlignStyle Where;
size_t Amount;
+ char Fill;
- FmtAlign(detail::format_adapter &Adapter, AlignStyle Where, size_t Amount)
- : Adapter(Adapter), Where(Where), Amount(Amount) {}
+ FmtAlign(detail::format_adapter &Adapter, AlignStyle Where, size_t Amount,
+ char Fill = ' ')
+ : Adapter(Adapter), Where(Where), Amount(Amount), Fill(Fill) {}
void format(raw_ostream &S, StringRef Options) {
// If we don't need to align, we can format straight into the underlying
@@ -48,21 +50,27 @@ struct FmtAlign {
switch (Where) {
case AlignStyle::Left:
S << Item;
- S.indent(PadAmount);
+ fill(S, PadAmount);
break;
case AlignStyle::Center: {
size_t X = PadAmount / 2;
- S.indent(X);
+ fill(S, X);
S << Item;
- S.indent(PadAmount - X);
+ fill(S, PadAmount - X);
break;
}
default:
- S.indent(PadAmount);
+ fill(S, PadAmount);
S << Item;
break;
}
}
+
+private:
+ void fill(llvm::raw_ostream &S, uint32_t Count) {
+ for (uint32_t I = 0; I < Count; ++I)
+ S << Fill;
+ }
};
}
diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h
index bb840380d4d3..fd29865c8475 100644
--- a/include/llvm/Support/MathExtras.h
+++ b/include/llvm/Support/MathExtras.h
@@ -272,23 +272,22 @@ T reverseBits(T Val) {
// type overloading so that signed and unsigned integers can be used without
// ambiguity.
-/// Hi_32 - This function returns the high 32 bits of a 64 bit value.
+/// Return the high 32 bits of a 64 bit value.
constexpr inline uint32_t Hi_32(uint64_t Value) {
return static_cast<uint32_t>(Value >> 32);
}
-/// Lo_32 - This function returns the low 32 bits of a 64 bit value.
+/// Return the low 32 bits of a 64 bit value.
constexpr inline uint32_t Lo_32(uint64_t Value) {
return static_cast<uint32_t>(Value);
}
-/// Make_64 - This functions makes a 64-bit integer from a high / low pair of
-/// 32-bit integers.
+/// Make a 64-bit integer from a high / low pair of 32-bit integers.
constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) {
return ((uint64_t)High << 32) | (uint64_t)Low;
}
-/// isInt - Checks if an integer fits into the given bit width.
+/// Checks if an integer fits into the given bit width.
template <unsigned N> constexpr inline bool isInt(int64_t x) {
return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
}
@@ -303,8 +302,7 @@ template <> constexpr inline bool isInt<32>(int64_t x) {
return static_cast<int32_t>(x) == x;
}
-/// isShiftedInt<N,S> - Checks if a signed integer is an N bit number shifted
-/// left by S.
+/// Checks if a signed integer is an N bit number shifted left by S.
template <unsigned N, unsigned S>
constexpr inline bool isShiftedInt(int64_t x) {
static_assert(
@@ -313,7 +311,7 @@ constexpr inline bool isShiftedInt(int64_t x) {
return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
}
-/// isUInt - Checks if an unsigned integer fits into the given bit width.
+/// Checks if an unsigned integer fits into the given bit width.
///
/// This is written as two functions rather than as simply
///
@@ -383,71 +381,63 @@ inline int64_t maxIntN(int64_t N) {
return (UINT64_C(1) << (N - 1)) - 1;
}
-/// isUIntN - Checks if an unsigned integer fits into the given (dynamic)
-/// bit width.
+/// Checks if an unsigned integer fits into the given (dynamic) bit width.
inline bool isUIntN(unsigned N, uint64_t x) {
return N >= 64 || x <= maxUIntN(N);
}
-/// isIntN - Checks if an signed integer fits into the given (dynamic)
-/// bit width.
+/// Checks if an signed integer fits into the given (dynamic) bit width.
inline bool isIntN(unsigned N, int64_t x) {
return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N));
}
-/// isMask_32 - This function returns true if the argument is a non-empty
-/// sequence of ones starting at the least significant bit with the remainder
-/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true.
+/// Return true if the argument is a non-empty sequence of ones starting at the
+/// least significant bit with the remainder zero (32 bit version).
+/// Ex. isMask_32(0x0000FFFFU) == true.
constexpr inline bool isMask_32(uint32_t Value) {
return Value && ((Value + 1) & Value) == 0;
}
-/// isMask_64 - This function returns true if the argument is a non-empty
-/// sequence of ones starting at the least significant bit with the remainder
-/// zero (64 bit version).
+/// Return true if the argument is a non-empty sequence of ones starting at the
+/// least significant bit with the remainder zero (64 bit version).
constexpr inline bool isMask_64(uint64_t Value) {
return Value && ((Value + 1) & Value) == 0;
}
-/// isShiftedMask_32 - This function returns true if the argument contains a
-/// non-empty sequence of ones with the remainder zero (32 bit version.)
-/// Ex. isShiftedMask_32(0x0000FF00U) == true.
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (32 bit version.) Ex. isShiftedMask_32(0x0000FF00U) == true.
constexpr inline bool isShiftedMask_32(uint32_t Value) {
return Value && isMask_32((Value - 1) | Value);
}
-/// isShiftedMask_64 - This function returns true if the argument contains a
-/// non-empty sequence of ones with the remainder zero (64 bit version.)
+/// Return true if the argument contains a non-empty sequence of ones with the
+/// remainder zero (64 bit version.)
constexpr inline bool isShiftedMask_64(uint64_t Value) {
return Value && isMask_64((Value - 1) | Value);
}
-/// isPowerOf2_32 - This function returns true if the argument is a power of
-/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
+/// Return true if the argument is a power of two > 0.
+/// Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
constexpr inline bool isPowerOf2_32(uint32_t Value) {
return Value && !(Value & (Value - 1));
}
-/// isPowerOf2_64 - This function returns true if the argument is a power of two
-/// > 0 (64 bit edition.)
+/// Return true if the argument is a power of two > 0 (64 bit edition.)
constexpr inline bool isPowerOf2_64(uint64_t Value) {
return Value && !(Value & (Value - int64_t(1L)));
}
-/// ByteSwap_16 - This function returns a byte-swapped representation of the
-/// 16-bit argument, Value.
+/// Return a byte-swapped representation of the 16-bit argument.
inline uint16_t ByteSwap_16(uint16_t Value) {
return sys::SwapByteOrder_16(Value);
}
-/// ByteSwap_32 - This function returns a byte-swapped representation of the
-/// 32-bit argument, Value.
+/// Return a byte-swapped representation of the 32-bit argument.
inline uint32_t ByteSwap_32(uint32_t Value) {
return sys::SwapByteOrder_32(Value);
}
-/// ByteSwap_64 - This function returns a byte-swapped representation of the
-/// 64-bit argument, Value.
+/// Return a byte-swapped representation of the 64-bit argument.
inline uint64_t ByteSwap_64(uint64_t Value) {
return sys::SwapByteOrder_64(Value);
}
@@ -455,7 +445,7 @@ inline uint64_t ByteSwap_64(uint64_t Value) {
/// \brief Count the number of ones from the most significant bit to the first
/// zero bit.
///
-/// Ex. CountLeadingOnes(0xFF0FFF00) == 8.
+/// Ex. countLeadingOnes(0xFF0FFF00) == 8.
/// Only unsigned integral types are allowed.
///
/// \param ZB the behavior on an input of all ones. Only ZB_Width and
@@ -526,7 +516,7 @@ inline unsigned countPopulation(T Value) {
return detail::PopulationCounter<T, sizeof(T)>::count(Value);
}
-/// Log2 - This function returns the log base 2 of the specified value
+/// Return the log base 2 of the specified value.
inline double Log2(double Value) {
#if defined(__ANDROID_API__) && __ANDROID_API__ < 18
return __builtin_log(Value) / __builtin_log(2.0);
@@ -535,34 +525,33 @@ inline double Log2(double Value) {
#endif
}
-/// Log2_32 - This function returns the floor log base 2 of the specified value,
-/// -1 if the value is zero. (32 bit edition.)
+/// Return the floor log base 2 of the specified value, -1 if the value is zero.
+/// (32 bit edition.)
/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
inline unsigned Log2_32(uint32_t Value) {
return 31 - countLeadingZeros(Value);
}
-/// Log2_64 - This function returns the floor log base 2 of the specified value,
-/// -1 if the value is zero. (64 bit edition.)
+/// Return the floor log base 2 of the specified value, -1 if the value is zero.
+/// (64 bit edition.)
inline unsigned Log2_64(uint64_t Value) {
return 63 - countLeadingZeros(Value);
}
-/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified
-/// value, 32 if the value is zero. (32 bit edition).
+/// Return the ceil log base 2 of the specified value, 32 if the value is zero.
+/// (32 bit edition).
/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
inline unsigned Log2_32_Ceil(uint32_t Value) {
return 32 - countLeadingZeros(Value - 1);
}
-/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified
-/// value, 64 if the value is zero. (64 bit edition.)
+/// Return the ceil log base 2 of the specified value, 64 if the value is zero.
+/// (64 bit edition.)
inline unsigned Log2_64_Ceil(uint64_t Value) {
return 64 - countLeadingZeros(Value - 1);
}
-/// GreatestCommonDivisor64 - Return the greatest common divisor of the two
-/// values using Euclid's algorithm.
+/// Return the greatest common divisor of the values using Euclid's algorithm.
inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
while (B) {
uint64_t T = B;
@@ -572,8 +561,7 @@ inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) {
return A;
}
-/// BitsToDouble - This function takes a 64-bit integer and returns the bit
-/// equivalent double.
+/// This function takes a 64-bit integer and returns the bit equivalent double.
inline double BitsToDouble(uint64_t Bits) {
double D;
static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
@@ -581,8 +569,7 @@ inline double BitsToDouble(uint64_t Bits) {
return D;
}
-/// BitsToFloat - This function takes a 32-bit integer and returns the bit
-/// equivalent float.
+/// This function takes a 32-bit integer and returns the bit equivalent float.
inline float BitsToFloat(uint32_t Bits) {
float F;
static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
@@ -590,10 +577,9 @@ inline float BitsToFloat(uint32_t Bits) {
return F;
}
-/// DoubleToBits - This function takes a double and returns the bit
-/// equivalent 64-bit integer. Note that copying doubles around
-/// changes the bits of NaNs on some hosts, notably x86, so this
-/// routine cannot be used if these bits are needed.
+/// This function takes a double and returns the bit equivalent 64-bit integer.
+/// Note that copying doubles around changes the bits of NaNs on some hosts,
+/// notably x86, so this routine cannot be used if these bits are needed.
inline uint64_t DoubleToBits(double Double) {
uint64_t Bits;
static_assert(sizeof(uint64_t) == sizeof(double), "Unexpected type sizes");
@@ -601,10 +587,9 @@ inline uint64_t DoubleToBits(double Double) {
return Bits;
}
-/// FloatToBits - This function takes a float and returns the bit
-/// equivalent 32-bit integer. Note that copying floats around
-/// changes the bits of NaNs on some hosts, notably x86, so this
-/// routine cannot be used if these bits are needed.
+/// This function takes a float and returns the bit equivalent 32-bit integer.
+/// Note that copying floats around changes the bits of NaNs on some hosts,
+/// notably x86, so this routine cannot be used if these bits are needed.
inline uint32_t FloatToBits(float Float) {
uint32_t Bits;
static_assert(sizeof(uint32_t) == sizeof(float), "Unexpected type sizes");
@@ -612,8 +597,8 @@ inline uint32_t FloatToBits(float Float) {
return Bits;
}
-/// MinAlign - A and B are either alignments or offsets. Return the minimum
-/// alignment that may be assumed after adding the two together.
+/// A and B are either alignments or offsets. Return the minimum alignment that
+/// may be assumed after adding the two together.
constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
// The largest power of 2 that divides both A and B.
//
@@ -642,8 +627,8 @@ inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
}
-/// NextPowerOf2 - Returns the next power of two (in 64-bits)
-/// that is strictly greater than A. Returns zero on overflow.
+/// Returns the next power of two (in 64-bits) that is strictly greater than A.
+/// Returns zero on overflow.
inline uint64_t NextPowerOf2(uint64_t A) {
A |= (A >> 1);
A |= (A >> 2);
diff --git a/include/llvm/Support/ThreadPool.h b/include/llvm/Support/ThreadPool.h
index f0e3ffa0999c..9ada946c6dae 100644
--- a/include/llvm/Support/ThreadPool.h
+++ b/include/llvm/Support/ThreadPool.h
@@ -35,17 +35,8 @@ namespace llvm {
/// for some work to become available.
class ThreadPool {
public:
-#ifndef _MSC_VER
- using VoidTy = void;
using TaskTy = std::function<void()>;
using PackagedTaskTy = std::packaged_task<void()>;
-#else
- // MSVC 2013 has a bug and can't use std::packaged_task<void()>;
- // We force it to use bool(bool) instead.
- using VoidTy = bool;
- using TaskTy = std::function<bool(bool)>;
- using PackagedTaskTy = std::packaged_task<bool(bool)>;
-#endif
/// Construct a pool with the number of core available on the system (or
/// whatever the value returned by std::thread::hardware_concurrency() is).
@@ -60,30 +51,17 @@ public:
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
template <typename Function, typename... Args>
- inline std::shared_future<VoidTy> async(Function &&F, Args &&... ArgList) {
+ inline std::shared_future<void> async(Function &&F, Args &&... ArgList) {
auto Task =
std::bind(std::forward<Function>(F), std::forward<Args>(ArgList)...);
-#ifndef _MSC_VER
return asyncImpl(std::move(Task));
-#else
- // This lambda has to be marked mutable because MSVC 2013's std::bind call
- // operator isn't const qualified.
- return asyncImpl([Task](VoidTy) mutable -> VoidTy {
- Task();
- return VoidTy();
- });
-#endif
}
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
template <typename Function>
- inline std::shared_future<VoidTy> async(Function &&F) {
-#ifndef _MSC_VER
+ inline std::shared_future<void> async(Function &&F) {
return asyncImpl(std::forward<Function>(F));
-#else
- return asyncImpl([F] (VoidTy) -> VoidTy { F(); return VoidTy(); });
-#endif
}
/// Blocking wait for all the threads to complete and the queue to be empty.
@@ -93,7 +71,7 @@ public:
private:
/// Asynchronous submission of a task to the pool. The returned future can be
/// used to wait for the task to finish and is *non-blocking* on destruction.
- std::shared_future<VoidTy> asyncImpl(TaskTy F);
+ std::shared_future<void> asyncImpl(TaskTy F);
/// Threads in flight
std::vector<llvm::thread> Threads;
diff --git a/include/llvm/TableGen/Main.h b/include/llvm/TableGen/Main.h
index 866b9868deb5..ca8c95cb6da2 100644
--- a/include/llvm/TableGen/Main.h
+++ b/include/llvm/TableGen/Main.h
@@ -16,13 +16,15 @@
namespace llvm {
-class RecordKeeper;
class raw_ostream;
+class RecordKeeper;
+
/// \brief Perform the action using Records, and write output to OS.
/// \returns true on error, false otherwise
-typedef bool TableGenMainFn(raw_ostream &OS, RecordKeeper &Records);
+using TableGenMainFn = bool (raw_ostream &OS, RecordKeeper &Records);
int TableGenMain(char *argv0, TableGenMainFn *MainFn);
-}
-#endif
+} // end namespace llvm
+
+#endif // LLVM_TABLEGEN_MAIN_H
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 5c3bf88fbbfa..fa9ca285bcde 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -38,11 +38,11 @@
namespace llvm {
class ListRecTy;
+struct MultiClass;
class Record;
class RecordKeeper;
class RecordVal;
class StringInit;
-struct MultiClass;
//===----------------------------------------------------------------------===//
// Type Classes
@@ -90,7 +90,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const RecTy &Ty) {
}
/// 'bit' - Represent a single bit
-///
class BitRecTy : public RecTy {
static BitRecTy Shared;
@@ -109,7 +108,6 @@ public:
};
/// 'bits<n>' - Represent a fixed number of bits
-///
class BitsRecTy : public RecTy {
unsigned Size;
@@ -130,7 +128,6 @@ public:
};
/// 'code' - Represent a code fragment
-///
class CodeRecTy : public RecTy {
static CodeRecTy Shared;
@@ -147,7 +144,6 @@ public:
};
/// 'int' - Represent an integer value of no particular size
-///
class IntRecTy : public RecTy {
static IntRecTy Shared;
@@ -166,7 +162,6 @@ public:
};
/// 'string' - Represent an string value
-///
class StringRecTy : public RecTy {
static StringRecTy Shared;
@@ -185,14 +180,13 @@ public:
/// 'list<Ty>' - Represent a list of values, all of which must be of
/// the specified type.
-///
class ListRecTy : public RecTy {
+ friend ListRecTy *RecTy::getListTy();
+
RecTy *Ty;
explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {}
- friend ListRecTy *RecTy::getListTy();
-
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == ListRecTyKind;
@@ -207,7 +201,6 @@ public:
};
/// 'dag' - Represent a dag fragment
-///
class DagRecTy : public RecTy {
static DagRecTy Shared;
@@ -225,14 +218,13 @@ public:
/// '[classname]' - Represent an instance of a class, such as:
/// (R32 X = EAX).
-///
class RecordRecTy : public RecTy {
+ friend class Record;
+
Record *Rec;
explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {}
- friend class Record;
-
public:
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == RecordRecTyKind;
@@ -249,7 +241,6 @@ public:
/// Find a common type that T1 and T2 convert to.
/// Return 0 if no such type exists.
-///
RecTy *resolveTypes(RecTy *T1, RecTy *T2);
//===----------------------------------------------------------------------===//
@@ -341,7 +332,6 @@ public:
/// selection operator. Given an initializer, it selects the specified bits
/// out, returning them as a new init of bits type. If it is not legal to use
/// the bit subscript operator on this initializer, return null.
- ///
virtual Init *convertInitializerBitRange(ArrayRef<unsigned> Bits) const {
return nullptr;
}
@@ -350,7 +340,6 @@ public:
/// selection operator. Given an initializer, it selects the specified list
/// elements, returning them as a new init of list type. If it is not legal
/// to take a slice of this, return null.
- ///
virtual Init *convertInitListSlice(ArrayRef<unsigned> Elements) const {
return nullptr;
}
@@ -358,7 +347,6 @@ public:
/// This method is used to implement the FieldInit class.
/// Implementors of this method should return the type of the named field if
/// they are of record type.
- ///
virtual RecTy *getFieldType(StringInit *FieldName) const {
return nullptr;
}
@@ -366,7 +354,6 @@ public:
/// This method complements getFieldType to return the
/// initializer for the specified field. If getFieldType returns non-null
/// this method should return non-null, otherwise it returns null.
- ///
virtual Init *getFieldInit(Record &R, const RecordVal *RV,
StringInit *FieldName) const {
return nullptr;
@@ -376,7 +363,6 @@ public:
/// variables which may not be defined at the time the expression is formed.
/// If a value is set for the variable later, this method will be called on
/// users of the value to allow the value to propagate out.
- ///
virtual Init *resolveReferences(Record &R, const RecordVal *RV) const {
return const_cast<Init *>(this);
}
@@ -400,7 +386,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const Init &I) {
/// This is the common super-class of types that have a specific,
/// explicit, type.
-///
class TypedInit : public Init {
RecTy *Ty;
@@ -409,8 +394,8 @@ protected:
: Init(K, Opc), Ty(T) {}
public:
- TypedInit(const TypedInit &Other) = delete;
- TypedInit &operator=(const TypedInit &Other) = delete;
+ TypedInit(const TypedInit &) = delete;
+ TypedInit &operator=(const TypedInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() >= IK_FirstTypedInit &&
@@ -438,13 +423,12 @@ public:
};
/// '?' - Represents an uninitialized value
-///
class UnsetInit : public Init {
UnsetInit() : Init(IK_UnsetInit) {}
public:
UnsetInit(const UnsetInit &) = delete;
- UnsetInit &operator=(const UnsetInit &Other) = delete;
+ UnsetInit &operator=(const UnsetInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_UnsetInit;
@@ -463,15 +447,14 @@ public:
};
/// 'true'/'false' - Represent a concrete initializer for a bit.
-///
class BitInit : public Init {
bool Value;
explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
public:
- BitInit(const BitInit &Other) = delete;
- BitInit &operator=(BitInit &Other) = delete;
+ BitInit(const BitInit &) = delete;
+ BitInit &operator=(BitInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_BitInit;
@@ -493,7 +476,6 @@ public:
/// '{ a, b, c }' - Represents an initializer for a BitsRecTy value.
/// It contains a vector of bits, whose size is determined by the type.
-///
class BitsInit final : public TypedInit, public FoldingSetNode,
public TrailingObjects<BitsInit, Init *> {
unsigned NumBits;
@@ -502,8 +484,8 @@ class BitsInit final : public TypedInit, public FoldingSetNode,
: TypedInit(IK_BitsInit, BitsRecTy::get(N)), NumBits(N) {}
public:
- BitsInit(const BitsInit &Other) = delete;
- BitsInit &operator=(const BitsInit &Other) = delete;
+ BitsInit(const BitsInit &) = delete;
+ BitsInit &operator=(const BitsInit &) = delete;
// Do not use sized deallocation due to trailing objects.
void operator delete(void *p) { ::operator delete(p); }
@@ -552,7 +534,6 @@ public:
};
/// '7' - Represent an initialization by a literal integer value.
-///
class IntInit : public TypedInit {
int64_t Value;
@@ -560,8 +541,8 @@ class IntInit : public TypedInit {
: TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {}
public:
- IntInit(const IntInit &Other) = delete;
- IntInit &operator=(const IntInit &Other) = delete;
+ IntInit(const IntInit &) = delete;
+ IntInit &operator=(const IntInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_IntInit;
@@ -590,7 +571,6 @@ public:
};
/// "foo" - Represent an initialization by a string value.
-///
class StringInit : public TypedInit {
StringRef Value;
@@ -598,8 +578,8 @@ class StringInit : public TypedInit {
: TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
public:
- StringInit(const StringInit &Other) = delete;
- StringInit &operator=(const StringInit &Other) = delete;
+ StringInit(const StringInit &) = delete;
+ StringInit &operator=(const StringInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_StringInit;
@@ -636,8 +616,8 @@ class CodeInit : public TypedInit {
Value(V) {}
public:
- CodeInit(const StringInit &Other) = delete;
- CodeInit &operator=(const StringInit &Other) = delete;
+ CodeInit(const StringInit &) = delete;
+ CodeInit &operator=(const StringInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_CodeInit;
@@ -675,15 +655,15 @@ class ListInit final : public TypedInit, public FoldingSetNode,
unsigned NumValues;
public:
- typedef Init *const *const_iterator;
+ using const_iterator = Init *const *;
private:
explicit ListInit(unsigned N, RecTy *EltTy)
: TypedInit(IK_ListInit, ListRecTy::get(EltTy)), NumValues(N) {}
public:
- ListInit(const ListInit &Other) = delete;
- ListInit &operator=(const ListInit &Other) = delete;
+ ListInit(const ListInit &) = delete;
+ ListInit &operator=(const ListInit &) = delete;
// Do not use sized deallocation due to trailing objects.
void operator delete(void *p) { ::operator delete(p); }
@@ -744,8 +724,8 @@ protected:
: TypedInit(K, Type, Opc) {}
public:
- OpInit(const OpInit &Other) = delete;
- OpInit &operator=(OpInit &Other) = delete;
+ OpInit(const OpInit &) = delete;
+ OpInit &operator=(OpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() >= IK_FirstOpInit &&
@@ -781,8 +761,8 @@ private:
: OpInit(IK_UnOpInit, Type, opc), LHS(lhs) {}
public:
- UnOpInit(const UnOpInit &Other) = delete;
- UnOpInit &operator=(const UnOpInit &Other) = delete;
+ UnOpInit(const UnOpInit &) = delete;
+ UnOpInit &operator=(const UnOpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_UnOpInit;
@@ -819,7 +799,6 @@ public:
};
/// !op (X, Y) - Combine two inits.
-///
class BinOpInit : public OpInit, public FoldingSetNode {
public:
enum BinaryOp : uint8_t { ADD, AND, OR, SHL, SRA, SRL, LISTCONCAT,
@@ -832,8 +811,8 @@ private:
OpInit(IK_BinOpInit, Type, opc), LHS(lhs), RHS(rhs) {}
public:
- BinOpInit(const BinOpInit &Other) = delete;
- BinOpInit &operator=(const BinOpInit &Other) = delete;
+ BinOpInit(const BinOpInit &) = delete;
+ BinOpInit &operator=(const BinOpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_BinOpInit;
@@ -874,7 +853,6 @@ public:
};
/// !op (X, Y, Z) - Combine two inits.
-///
class TernOpInit : public OpInit, public FoldingSetNode {
public:
enum TernaryOp : uint8_t { SUBST, FOREACH, IF };
@@ -887,8 +865,8 @@ private:
OpInit(IK_TernOpInit, Type, opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
public:
- TernOpInit(const TernOpInit &Other) = delete;
- TernOpInit &operator=(const TernOpInit &Other) = delete;
+ TernOpInit(const TernOpInit &) = delete;
+ TernOpInit &operator=(const TernOpInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_TernOpInit;
@@ -935,7 +913,6 @@ public:
};
/// 'Opcode' - Represent a reference to an entire variable object.
-///
class VarInit : public TypedInit {
Init *VarName;
@@ -943,8 +920,8 @@ class VarInit : public TypedInit {
: TypedInit(IK_VarInit, T), VarName(VN) {}
public:
- VarInit(const VarInit &Other) = delete;
- VarInit &operator=(const VarInit &Other) = delete;
+ VarInit(const VarInit &) = delete;
+ VarInit &operator=(const VarInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_VarInit;
@@ -980,7 +957,6 @@ public:
};
/// Opcode{0} - Represent access to one bit of a variable or field.
-///
class VarBitInit : public Init {
TypedInit *TI;
unsigned Bit;
@@ -994,8 +970,8 @@ class VarBitInit : public Init {
}
public:
- VarBitInit(const VarBitInit &Other) = delete;
- VarBitInit &operator=(const VarBitInit &Other) = delete;
+ VarBitInit(const VarBitInit &) = delete;
+ VarBitInit &operator=(const VarBitInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_VarBitInit;
@@ -1032,8 +1008,8 @@ class VarListElementInit : public TypedInit {
}
public:
- VarListElementInit(const VarListElementInit &Other) = delete;
- void operator=(const VarListElementInit &Other) = delete;
+ VarListElementInit(const VarListElementInit &) = delete;
+ VarListElementInit &operator=(const VarListElementInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_VarListElementInit;
@@ -1057,17 +1033,16 @@ public:
};
/// AL - Represent a reference to a 'def' in the description
-///
class DefInit : public TypedInit {
+ friend class Record;
+
Record *Def;
DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {}
- friend class Record;
-
public:
- DefInit(const DefInit &Other) = delete;
- DefInit &operator=(const DefInit &Other) = delete;
+ DefInit(const DefInit &) = delete;
+ DefInit &operator=(const DefInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_DefInit;
@@ -1101,7 +1076,6 @@ public:
};
/// X.Y - Represent a reference to a subfield of a variable
-///
class FieldInit : public TypedInit {
Init *Rec; // Record we are referring to
StringInit *FieldName; // Field we are accessing
@@ -1112,8 +1086,8 @@ class FieldInit : public TypedInit {
}
public:
- FieldInit(const FieldInit &Other) = delete;
- FieldInit &operator=(const FieldInit &Other) = delete;
+ FieldInit(const FieldInit &) = delete;
+ FieldInit &operator=(const FieldInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_FieldInit;
@@ -1136,9 +1110,10 @@ public:
/// (v a, b) - Represent a DAG tree value. DAG inits are required
/// to have at least one value then a (possibly empty) list of arguments. Each
/// argument can have a name associated with it.
-///
class DagInit final : public TypedInit, public FoldingSetNode,
public TrailingObjects<DagInit, Init *, StringInit *> {
+ friend TrailingObjects;
+
Init *Val;
StringInit *ValName;
unsigned NumArgs;
@@ -1148,12 +1123,11 @@ class DagInit final : public TypedInit, public FoldingSetNode,
: TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN),
NumArgs(NumArgs), NumArgNames(NumArgNames) {}
- friend TrailingObjects;
size_t numTrailingObjects(OverloadToken<Init *>) const { return NumArgs; }
public:
- DagInit(const DagInit &Other) = delete;
- DagInit &operator=(const DagInit &Other) = delete;
+ DagInit(const DagInit &) = delete;
+ DagInit &operator=(const DagInit &) = delete;
static bool classof(const Init *I) {
return I->getKind() == IK_DagInit;
@@ -1171,19 +1145,23 @@ public:
Init *getOperator() const { return Val; }
StringInit *getName() const { return ValName; }
+
StringRef getNameStr() const {
return ValName ? ValName->getValue() : StringRef();
}
unsigned getNumArgs() const { return NumArgs; }
+
Init *getArg(unsigned Num) const {
assert(Num < NumArgs && "Arg number out of range!");
return getTrailingObjects<Init *>()[Num];
}
+
StringInit *getArgName(unsigned Num) const {
assert(Num < NumArgNames && "Arg number out of range!");
return getTrailingObjects<StringInit *>()[Num];
}
+
StringRef getArgNameStr(unsigned Num) const {
StringInit *Init = getArgName(Num);
return Init ? Init->getValue() : StringRef();
@@ -1192,6 +1170,7 @@ public:
ArrayRef<Init *> getArgs() const {
return makeArrayRef(getTrailingObjects<Init *>(), NumArgs);
}
+
ArrayRef<StringInit *> getArgNames() const {
return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames);
}
@@ -1200,8 +1179,8 @@ public:
std::string getAsString() const override;
- typedef SmallVectorImpl<Init*>::const_iterator const_arg_iterator;
- typedef SmallVectorImpl<StringInit*>::const_iterator const_name_iterator;
+ using const_arg_iterator = SmallVectorImpl<Init*>::const_iterator;
+ using const_name_iterator = SmallVectorImpl<StringInit*>::const_iterator;
inline const_arg_iterator arg_begin() const { return getArgs().begin(); }
inline const_arg_iterator arg_end () const { return getArgs().end(); }
@@ -1231,6 +1210,7 @@ public:
class RecordVal {
friend class Record;
+
Init *Name;
PointerIntPair<RecTy *, 1, bool> TyAndPrefix;
Init *Value;
@@ -1298,7 +1278,7 @@ class Record {
// definitions that use them (e.g. Def). However, inside a multiclass they
// can't be immediately resolved so we mark them ResolveFirst to fully
// resolve them later as soon as the multiclass is instantiated.
- bool ResolveFirst;
+ bool ResolveFirst = false;
void init();
void checkName();
@@ -1308,7 +1288,7 @@ public:
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
bool Anonymous = false) :
Name(N), Locs(locs.begin(), locs.end()), TrackedRecords(records),
- ID(LastID++), IsAnonymous(Anonymous), ResolveFirst(false) {
+ ID(LastID++), IsAnonymous(Anonymous) {
init();
}
@@ -1330,6 +1310,7 @@ public:
unsigned getID() const { return ID; }
StringRef getName() const;
+
Init *getNameInit() const {
return Name;
}
@@ -1435,7 +1416,6 @@ public:
/// If there are any field references that refer to fields
/// that have been filled in, we can propagate the values now.
- ///
void resolveReferences() { resolveReferencesTo(nullptr); }
/// If anything in this record refers to RV, replace the
@@ -1468,7 +1448,6 @@ public:
/// Return the initializer for a value with the specified name,
/// or throw an exception if the field does not exist.
- ///
Init *getValueInit(StringRef FieldName) const;
/// Return true if the named field is unset.
@@ -1479,67 +1458,56 @@ public:
/// This method looks up the specified field and returns
/// its value as a string, throwing an exception if the field does not exist
/// or if the value is not a string.
- ///
StringRef getValueAsString(StringRef FieldName) const;
/// This method looks up the specified field and returns
/// its value as a BitsInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
- ///
BitsInit *getValueAsBitsInit(StringRef FieldName) const;
/// This method looks up the specified field and returns
/// its value as a ListInit, throwing an exception if the field does not exist
/// or if the value is not the right type.
- ///
ListInit *getValueAsListInit(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a vector of records, throwing an exception if the
/// field does not exist or if the value is not the right type.
- ///
std::vector<Record*> getValueAsListOfDefs(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a vector of integers, throwing an exception if the
/// field does not exist or if the value is not the right type.
- ///
std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a vector of strings, throwing an exception if the
/// field does not exist or if the value is not the right type.
- ///
std::vector<StringRef> getValueAsListOfStrings(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if
/// the value is not the right type.
- ///
Record *getValueAsDef(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as a bit, throwing an exception if the field does not exist or if
/// the value is not the right type.
- ///
bool getValueAsBit(StringRef FieldName) const;
/// This method looks up the specified field and
/// returns its value as a bit. If the field is unset, sets Unset to true and
/// returns false.
- ///
bool getValueAsBitOrUnset(StringRef FieldName, bool &Unset) const;
/// This method looks up the specified field and returns its
/// value as an int64_t, throwing an exception if the field does not exist or
/// if the value is not the right type.
- ///
int64_t getValueAsInt(StringRef FieldName) const;
/// This method looks up the specified field and returns its
/// value as an Dag, throwing an exception if the field does not exist or if
/// the value is not the right type.
- ///
DagInit *getValueAsDag(StringRef FieldName) const;
};
@@ -1547,7 +1515,7 @@ raw_ostream &operator<<(raw_ostream &OS, const Record &R);
struct MultiClass {
Record Rec; // Placeholder for template args and Name.
- typedef std::vector<std::unique_ptr<Record>> RecordVector;
+ using RecordVector = std::vector<std::unique_ptr<Record>>;
RecordVector DefPrototypes;
void dump() const;
@@ -1557,7 +1525,7 @@ struct MultiClass {
};
class RecordKeeper {
- typedef std::map<std::string, std::unique_ptr<Record>> RecordMap;
+ using RecordMap = std::map<std::string, std::unique_ptr<Record>>;
RecordMap Classes, Defs;
public:
@@ -1600,7 +1568,6 @@ public:
};
/// Sorting predicate to sort record pointers by name.
-///
struct LessRecord {
bool operator()(const Record *Rec1, const Record *Rec2) const {
return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
@@ -1619,7 +1586,6 @@ struct LessRecordByID {
/// Sorting predicate to sort record pointers by their
/// name field.
-///
struct LessRecordFieldName {
bool operator()(const Record *Rec1, const Record *Rec2) const {
return Rec1->getValueAsString("Name") < Rec2->getValueAsString("Name");
diff --git a/include/llvm/TableGen/SetTheory.h b/include/llvm/TableGen/SetTheory.h
index 818b0549b66a..4b32f9e3da8f 100644
--- a/include/llvm/TableGen/SetTheory.h
+++ b/include/llvm/TableGen/SetTheory.h
@@ -64,8 +64,8 @@ class Record;
class SetTheory {
public:
- typedef std::vector<Record*> RecVec;
- typedef SmallSetVector<Record*, 16> RecSet;
+ using RecVec = std::vector<Record *>;
+ using RecSet = SmallSetVector<Record *, 16>;
/// Operator - A callback representing a DAG operator.
class Operator {
@@ -95,7 +95,7 @@ public:
private:
// Map set defs to their fully expanded contents. This serves as a memoization
// cache and it makes it possible to return const references on queries.
- typedef std::map<Record*, RecVec> ExpandMap;
+ using ExpandMap = std::map<Record *, RecVec>;
ExpandMap Expansions;
// Known DAG operators by name.
diff --git a/include/llvm/TableGen/StringMatcher.h b/include/llvm/TableGen/StringMatcher.h
index 11a8ad8183aa..7c919ffec7b6 100644
--- a/include/llvm/TableGen/StringMatcher.h
+++ b/include/llvm/TableGen/StringMatcher.h
@@ -20,7 +20,8 @@
#include <vector>
namespace llvm {
- class raw_ostream;
+
+class raw_ostream;
/// StringMatcher - Given a list of strings and code to execute when they match,
/// output a simple switch tree to classify the input string.
@@ -30,7 +31,7 @@ namespace llvm {
///
class StringMatcher {
public:
- typedef std::pair<std::string, std::string> StringPair;
+ using StringPair = std::pair<std::string, std::string>;
private:
StringRef StrVariableName;
@@ -49,6 +50,6 @@ private:
unsigned CharNo, unsigned IndentCount) const;
};
-} // end llvm namespace.
+} // end namespace llvm
-#endif
+#endif // LLVM_TABLEGEN_STRINGMATCHER_H
diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h
index 0ffd4b7f8c78..80d4d8e42e51 100644
--- a/include/llvm/Target/TargetLoweringObjectFile.h
+++ b/include/llvm/Target/TargetLoweringObjectFile.h
@@ -70,10 +70,9 @@ public:
virtual void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM,
const MCSymbol *Sym) const;
- /// Emit the module flags that the platform cares about.
- virtual void emitModuleFlags(MCStreamer &Streamer,
- ArrayRef<Module::ModuleFlagEntry> Flags,
- const TargetMachine &TM) const {}
+ /// Emit the module-level metadata that the platform cares about.
+ virtual void emitModuleMetadata(MCStreamer &Streamer, Module &M,
+ const TargetMachine &TM) const {}
/// Given a constant with the SectionKind, return a section that it should be
/// placed in.
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 4ce6d2ff5e26..86ad8ad53052 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -497,6 +497,16 @@ public:
/// function. Used by MachineRegisterInfo::isConstantPhysReg().
virtual bool isConstantPhysReg(unsigned PhysReg) const { return false; }
+ /// Physical registers that may be modified within a function but are
+ /// guaranteed to be restored before any uses. This is useful for targets that
+ /// have call sequences where a GOT register may be updated by the caller
+ /// prior to a call and is guaranteed to be restored (also by the caller)
+ /// after the call.
+ virtual bool isCallerPreservedPhysReg(unsigned PhysReg,
+ const MachineFunction &MF) const {
+ return false;
+ }
+
/// Prior to adding the live-out mask to a stackmap or patchpoint
/// instruction, provide the target the opportunity to adjust it (mainly to
/// remove pseudo-registers that should be ignored).
diff --git a/include/llvm/Testing/Support/Error.h b/include/llvm/Testing/Support/Error.h
new file mode 100644
index 000000000000..d52752901593
--- /dev/null
+++ b/include/llvm/Testing/Support/Error.h
@@ -0,0 +1,69 @@
+//===- llvm/Testing/Support/Error.h ---------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TESTING_SUPPORT_ERROR_H
+#define LLVM_TESTING_SUPPORT_ERROR_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/SupportHelpers.h"
+
+#include "gmock/gmock.h"
+#include <ostream>
+
+namespace llvm {
+namespace detail {
+ErrorHolder TakeError(Error Err);
+
+template <typename T> ExpectedHolder<T> TakeExpected(Expected<T> &Exp) {
+ llvm::detail::ExpectedHolder<T> Result;
+ auto &EH = static_cast<llvm::detail::ErrorHolder &>(Result);
+ EH = TakeError(Exp.takeError());
+ if (Result.Success)
+ Result.Value = &(*Exp);
+ return Result;
+}
+
+template <typename T> ExpectedHolder<T> TakeExpected(const Expected<T> &Exp) {
+ return TakeExpected(const_cast<Expected<T> &>(Exp));
+}
+} // namespace detail
+
+#define EXPECT_THAT_ERROR(Err, Matcher) \
+ EXPECT_THAT(llvm::detail::TakeError(Err), Matcher)
+#define ASSERT_THAT_ERROR(Err, Matcher) \
+ ASSERT_THAT(llvm::detail::TakeError(Err), Matcher)
+
+#define EXPECT_THAT_EXPECTED(Err, Matcher) \
+ EXPECT_THAT(llvm::detail::TakeExpected(Err), Matcher)
+#define ASSERT_THAT_EXPECTED(Err, Matcher) \
+ ASSERT_THAT(llvm::detail::TakeExpected(Err), Matcher)
+
+MATCHER(Succeeded, "") { return arg.Success; }
+MATCHER(Failed, "") { return !arg.Success; }
+
+MATCHER_P(HasValue, value,
+ "succeeded with value " + testing::PrintToString(value)) {
+ if (!arg.Success) {
+ *result_listener << "operation failed";
+ return false;
+ }
+
+ assert(arg.Value.hasValue());
+ if (**arg.Value != value) {
+ *result_listener << "but \"" + testing::PrintToString(**arg.Value) +
+ "\" != " + testing::PrintToString(value);
+ return false;
+ }
+
+ return true;
+}
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Testing/Support/SupportHelpers.h b/include/llvm/Testing/Support/SupportHelpers.h
new file mode 100644
index 000000000000..c4dd414b80db
--- /dev/null
+++ b/include/llvm/Testing/Support/SupportHelpers.h
@@ -0,0 +1,47 @@
+//===- Testing/Support/SupportHelpers.h -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H
+#define LLVM_TESTING_SUPPORT_SUPPORTHELPERS_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "gtest/gtest-printers.h"
+
+namespace llvm {
+namespace detail {
+struct ErrorHolder {
+ bool Success;
+ std::string Message;
+};
+
+template <typename T> struct ExpectedHolder : public ErrorHolder {
+ Optional<T *> Value;
+};
+
+inline void PrintTo(const ErrorHolder &Err, std::ostream *Out) {
+ *Out << (Err.Success ? "succeeded" : "failed");
+ if (!Err.Success) {
+ *Out << " (" << StringRef(Err.Message).trim().str() << ")";
+ }
+}
+
+template <typename T>
+void PrintTo(const ExpectedHolder<T> &Item, std::ostream *Out) {
+ if (Item.Success) {
+ *Out << "succeeded with value \"" << ::testing::PrintToString(**Item.Value)
+ << "\"";
+ } else {
+ PrintTo(static_cast<const ErrorHolder &>(Item), Out);
+ }
+}
+} // namespace detail
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Transforms/Scalar/GVNExpression.h b/include/llvm/Transforms/Scalar/GVNExpression.h
index 008341304995..f603ebcbca7c 100644
--- a/include/llvm/Transforms/Scalar/GVNExpression.h
+++ b/include/llvm/Transforms/Scalar/GVNExpression.h
@@ -121,10 +121,7 @@ public:
OS << "}";
}
- LLVM_DUMP_METHOD void dump() const {
- print(dbgs());
- dbgs() << "\n";
- }
+ LLVM_DUMP_METHOD void dump() const;
};
inline raw_ostream &operator<<(raw_ostream &OS, const Expression &E) {
diff --git a/include/llvm/Transforms/Utils/CodeExtractor.h b/include/llvm/Transforms/Utils/CodeExtractor.h
index 7e23544af1ab..682b353ab5ae 100644
--- a/include/llvm/Transforms/Utils/CodeExtractor.h
+++ b/include/llvm/Transforms/Utils/CodeExtractor.h
@@ -106,15 +106,32 @@ template <typename T> class ArrayRef;
/// significant impact on the cost however.
void findInputsOutputs(ValueSet &Inputs, ValueSet &Outputs,
const ValueSet &Allocas) const;
+
+ /// Check if life time marker nodes can be hoisted/sunk into the outline
+ /// region.
+ ///
+ /// Returns true if it is safe to do the code motion.
+ bool isLegalToShrinkwrapLifetimeMarkers(Instruction *AllocaAddr) const;
/// Find the set of allocas whose life ranges are contained within the
/// outlined region.
///
/// Allocas which have life_time markers contained in the outlined region
/// should be pushed to the outlined function. The address bitcasts that
/// are used by the lifetime markers are also candidates for shrink-
- /// wrapping. The instructions that need to be sinked are collected in
+ /// wrapping. The instructions that need to be sunk are collected in
/// 'Allocas'.
- void findAllocas(ValueSet &Allocas) const;
+ void findAllocas(ValueSet &SinkCands, ValueSet &HoistCands,
+ BasicBlock *&ExitBlock) const;
+
+ /// Find or create a block within the outline region for placing hoisted
+ /// code.
+ ///
+ /// CommonExitBlock is block outside the outline region. It is the common
+ /// successor of blocks inside the region. If there exists a single block
+ /// inside the region that is the predecessor of CommonExitBlock, that block
+ /// will be returned. Otherwise CommonExitBlock will be split and the
+ /// original block will be added to the outline region.
+ BasicBlock *findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock);
private:
void severSplitPHINodes(BasicBlock *&Header);
diff --git a/include/llvm/Transforms/Utils/Mem2Reg.h b/include/llvm/Transforms/Utils/Mem2Reg.h
index 456876b520b0..1fe186d6c3ad 100644
--- a/include/llvm/Transforms/Utils/Mem2Reg.h
+++ b/include/llvm/Transforms/Utils/Mem2Reg.h
@@ -25,4 +25,4 @@ public:
};
}
-#endif // LLVM_TRANSFORMS_UTILS_MEM2REG_H \ No newline at end of file
+#endif // LLVM_TRANSFORMS_UTILS_MEM2REG_H
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index f743cb234c45..dbb1b01b94ac 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/lib/Analysis/BasicAliasAnalysis.cpp
@@ -1011,10 +1011,24 @@ static AliasResult aliasSameBasePointerGEPs(const GEPOperator *GEP1,
// equal each other so we can exit early.
if (C1 && C2)
return NoAlias;
- if (isKnownNonEqual(GEP1->getOperand(GEP1->getNumOperands() - 1),
- GEP2->getOperand(GEP2->getNumOperands() - 1),
- DL))
- return NoAlias;
+ {
+ Value *GEP1LastIdx = GEP1->getOperand(GEP1->getNumOperands() - 1);
+ Value *GEP2LastIdx = GEP2->getOperand(GEP2->getNumOperands() - 1);
+ if (isa<PHINode>(GEP1LastIdx) || isa<PHINode>(GEP2LastIdx)) {
+ // If one of the indices is a PHI node, be safe and only use
+ // computeKnownBits so we don't make any assumptions about the
+ // relationships between the two indices. This is important if we're
+ // asking about values from different loop iterations. See PR32314.
+ // TODO: We may be able to change the check so we only do this when
+ // we definitely looked through a PHINode.
+ KnownBits Known1 = computeKnownBits(GEP1LastIdx, DL);
+ KnownBits Known2 = computeKnownBits(GEP2LastIdx, DL);
+ if (Known1.Zero.intersects(Known2.One) ||
+ Known1.One.intersects(Known2.Zero))
+ return NoAlias;
+ } else if (isKnownNonEqual(GEP1LastIdx, GEP2LastIdx, DL))
+ return NoAlias;
+ }
return MayAlias;
} else if (!LastIndexedStruct || !C1 || !C2) {
return MayAlias;
diff --git a/lib/Analysis/CallGraphSCCPass.cpp b/lib/Analysis/CallGraphSCCPass.cpp
index 5896e6e0902f..facda246936d 100644
--- a/lib/Analysis/CallGraphSCCPass.cpp
+++ b/lib/Analysis/CallGraphSCCPass.cpp
@@ -608,18 +608,18 @@ namespace {
}
bool runOnSCC(CallGraphSCC &SCC) override {
+ bool BannerPrinted = false;
auto PrintBannerOnce = [&] () {
- static bool BannerPrinted = false;
if (BannerPrinted)
return;
Out << Banner;
BannerPrinted = true;
};
for (CallGraphNode *CGN : SCC) {
- if (CGN->getFunction()) {
- if (isFunctionInPrintList(CGN->getFunction()->getName())) {
+ if (Function *F = CGN->getFunction()) {
+ if (!F->isDeclaration() && isFunctionInPrintList(F->getName())) {
PrintBannerOnce();
- CGN->getFunction()->print(Out);
+ F->print(Out);
}
} else if (llvm::isFunctionInPrintList("*")) {
PrintBannerOnce();
diff --git a/lib/Analysis/DivergenceAnalysis.cpp b/lib/Analysis/DivergenceAnalysis.cpp
index 1b36569f7a07..2d39a0b02150 100644
--- a/lib/Analysis/DivergenceAnalysis.cpp
+++ b/lib/Analysis/DivergenceAnalysis.cpp
@@ -241,7 +241,7 @@ void DivergencePropagator::exploreDataDependency(Value *V) {
// Follow def-use chains of V.
for (User *U : V->users()) {
Instruction *UserInst = cast<Instruction>(U);
- if (DV.insert(UserInst).second)
+ if (!TTI.isAlwaysUniform(U) && DV.insert(UserInst).second)
Worklist.push_back(UserInst);
}
}
diff --git a/lib/Analysis/MemorySSA.cpp b/lib/Analysis/MemorySSA.cpp
index e0e04a91410f..86d0d92799f2 100644
--- a/lib/Analysis/MemorySSA.cpp
+++ b/lib/Analysis/MemorySSA.cpp
@@ -1872,7 +1872,6 @@ MemorySSAPrinterLegacyPass::MemorySSAPrinterLegacyPass() : FunctionPass(ID) {
void MemorySSAPrinterLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<MemorySSAWrapperPass>();
- AU.addPreserved<MemorySSAWrapperPass>();
}
bool MemorySSAPrinterLegacyPass::runOnFunction(Function &F) {
@@ -1957,6 +1956,7 @@ MemoryAccess *MemorySSA::CachingWalker::getClobberingMemoryAccess(
#ifdef EXPENSIVE_CHECKS
MemoryAccess *NewNoCache = Walker.findClobber(StartingAccess, Q);
assert(NewNoCache == New && "Cache made us hand back a different result?");
+ (void)NewNoCache;
#endif
if (AutoResetWalker)
resetClobberWalker();
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index b9c4716b5528..aebc80a0a885 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -149,9 +149,9 @@ static cl::opt<unsigned> MaxValueCompareDepth(
cl::init(2));
static cl::opt<unsigned>
- MaxAddExprDepth("scalar-evolution-max-addexpr-depth", cl::Hidden,
- cl::desc("Maximum depth of recursive AddExpr"),
- cl::init(32));
+ MaxArithDepth("scalar-evolution-max-arith-depth", cl::Hidden,
+ cl::desc("Maximum depth of recursive arithmetics"),
+ cl::init(32));
static cl::opt<unsigned> MaxConstantEvolvingDepth(
"scalar-evolution-max-constant-evolving-depth", cl::Hidden,
@@ -2276,8 +2276,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
if (Ops.size() == 1) return Ops[0];
}
- // Limit recursion calls depth
- if (Depth > MaxAddExprDepth)
+ // Limit recursion calls depth.
+ if (Depth > MaxArithDepth)
return getOrCreateAddExpr(Ops, Flags);
// Okay, check to see if the same value occurs in the operand list more than
@@ -2293,7 +2293,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
++Count;
// Merge the values into a multiply.
const SCEV *Scale = getConstant(Ty, Count);
- const SCEV *Mul = getMulExpr(Scale, Ops[i]);
+ const SCEV *Mul = getMulExpr(Scale, Ops[i], SCEV::FlagAnyWrap, Depth + 1);
if (Ops.size() == Count)
return Mul;
Ops[i] = Mul;
@@ -2343,7 +2343,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
}
}
if (Ok)
- LargeOps.push_back(getMulExpr(LargeMulOps));
+ LargeOps.push_back(getMulExpr(LargeMulOps, SCEV::FlagAnyWrap, Depth + 1));
} else {
Ok = false;
break;
@@ -2417,7 +2417,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
if (MulOp.first != 0)
Ops.push_back(getMulExpr(
getConstant(MulOp.first),
- getAddExpr(MulOp.second, SCEV::FlagAnyWrap, Depth + 1)));
+ getAddExpr(MulOp.second, SCEV::FlagAnyWrap, Depth + 1),
+ SCEV::FlagAnyWrap, Depth + 1));
if (Ops.empty())
return getZero(Ty);
if (Ops.size() == 1)
@@ -2445,11 +2446,12 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SmallVector<const SCEV *, 4> MulOps(Mul->op_begin(),
Mul->op_begin()+MulOp);
MulOps.append(Mul->op_begin()+MulOp+1, Mul->op_end());
- InnerMul = getMulExpr(MulOps);
+ InnerMul = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
}
SmallVector<const SCEV *, 2> TwoOps = {getOne(Ty), InnerMul};
const SCEV *AddOne = getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
- const SCEV *OuterMul = getMulExpr(AddOne, MulOpSCEV);
+ const SCEV *OuterMul = getMulExpr(AddOne, MulOpSCEV,
+ SCEV::FlagAnyWrap, Depth + 1);
if (Ops.size() == 2) return OuterMul;
if (AddOp < Idx) {
Ops.erase(Ops.begin()+AddOp);
@@ -2478,19 +2480,20 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SmallVector<const SCEV *, 4> MulOps(Mul->op_begin(),
Mul->op_begin()+MulOp);
MulOps.append(Mul->op_begin()+MulOp+1, Mul->op_end());
- InnerMul1 = getMulExpr(MulOps);
+ InnerMul1 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
}
const SCEV *InnerMul2 = OtherMul->getOperand(OMulOp == 0);
if (OtherMul->getNumOperands() != 2) {
SmallVector<const SCEV *, 4> MulOps(OtherMul->op_begin(),
OtherMul->op_begin()+OMulOp);
MulOps.append(OtherMul->op_begin()+OMulOp+1, OtherMul->op_end());
- InnerMul2 = getMulExpr(MulOps);
+ InnerMul2 = getMulExpr(MulOps, SCEV::FlagAnyWrap, Depth + 1);
}
SmallVector<const SCEV *, 2> TwoOps = {InnerMul1, InnerMul2};
const SCEV *InnerMulSum =
getAddExpr(TwoOps, SCEV::FlagAnyWrap, Depth + 1);
- const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum);
+ const SCEV *OuterMul = getMulExpr(MulOpSCEV, InnerMulSum,
+ SCEV::FlagAnyWrap, Depth + 1);
if (Ops.size() == 2) return OuterMul;
Ops.erase(Ops.begin()+Idx);
Ops.erase(Ops.begin()+OtherMulIdx-1);
@@ -2621,6 +2624,27 @@ ScalarEvolution::getOrCreateAddExpr(SmallVectorImpl<const SCEV *> &Ops,
return S;
}
+const SCEV *
+ScalarEvolution::getOrCreateMulExpr(SmallVectorImpl<const SCEV *> &Ops,
+ SCEV::NoWrapFlags Flags) {
+ FoldingSetNodeID ID;
+ ID.AddInteger(scMulExpr);
+ for (unsigned i = 0, e = Ops.size(); i != e; ++i)
+ ID.AddPointer(Ops[i]);
+ void *IP = nullptr;
+ SCEVMulExpr *S =
+ static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
+ if (!S) {
+ const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
+ std::uninitialized_copy(Ops.begin(), Ops.end(), O);
+ S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator),
+ O, Ops.size());
+ UniqueSCEVs.InsertNode(S, IP);
+ }
+ S->setNoWrapFlags(Flags);
+ return S;
+}
+
static uint64_t umul_ov(uint64_t i, uint64_t j, bool &Overflow) {
uint64_t k = i*j;
if (j > 1 && k / j != i) Overflow = true;
@@ -2673,7 +2697,8 @@ static bool containsConstantSomewhere(const SCEV *StartExpr) {
/// Get a canonical multiply expression, or something simpler if possible.
const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
- SCEV::NoWrapFlags Flags) {
+ SCEV::NoWrapFlags Flags,
+ unsigned Depth) {
assert(Flags == maskFlags(Flags, SCEV::FlagNUW | SCEV::FlagNSW) &&
"only nuw or nsw allowed");
assert(!Ops.empty() && "Cannot get empty mul!");
@@ -2690,6 +2715,10 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
Flags = StrengthenNoWrapFlags(this, scMulExpr, Ops, Flags);
+ // Limit recursion calls depth.
+ if (Depth > MaxArithDepth)
+ return getOrCreateMulExpr(Ops, Flags);
+
// If there are any constants, fold them together.
unsigned Idx = 0;
if (const SCEVConstant *LHSC = dyn_cast<SCEVConstant>(Ops[0])) {
@@ -2701,8 +2730,11 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
// apply this transformation as well.
if (Add->getNumOperands() == 2)
if (containsConstantSomewhere(Add))
- return getAddExpr(getMulExpr(LHSC, Add->getOperand(0)),
- getMulExpr(LHSC, Add->getOperand(1)));
+ return getAddExpr(getMulExpr(LHSC, Add->getOperand(0),
+ SCEV::FlagAnyWrap, Depth + 1),
+ getMulExpr(LHSC, Add->getOperand(1),
+ SCEV::FlagAnyWrap, Depth + 1),
+ SCEV::FlagAnyWrap, Depth + 1);
++Idx;
while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) {
@@ -2730,17 +2762,19 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
SmallVector<const SCEV *, 4> NewOps;
bool AnyFolded = false;
for (const SCEV *AddOp : Add->operands()) {
- const SCEV *Mul = getMulExpr(Ops[0], AddOp);
+ const SCEV *Mul = getMulExpr(Ops[0], AddOp, SCEV::FlagAnyWrap,
+ Depth + 1);
if (!isa<SCEVMulExpr>(Mul)) AnyFolded = true;
NewOps.push_back(Mul);
}
if (AnyFolded)
- return getAddExpr(NewOps);
+ return getAddExpr(NewOps, SCEV::FlagAnyWrap, Depth + 1);
} else if (const auto *AddRec = dyn_cast<SCEVAddRecExpr>(Ops[1])) {
// Negation preserves a recurrence's no self-wrap property.
SmallVector<const SCEV *, 4> Operands;
for (const SCEV *AddRecOp : AddRec->operands())
- Operands.push_back(getMulExpr(Ops[0], AddRecOp));
+ Operands.push_back(getMulExpr(Ops[0], AddRecOp, SCEV::FlagAnyWrap,
+ Depth + 1));
return getAddRecExpr(Operands, AddRec->getLoop(),
AddRec->getNoWrapFlags(SCEV::FlagNW));
@@ -2762,18 +2796,18 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
while (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[Idx])) {
if (Ops.size() > MulOpsInlineThreshold)
break;
- // If we have an mul, expand the mul operands onto the end of the operands
- // list.
+ // If we have an mul, expand the mul operands onto the end of the
+ // operands list.
Ops.erase(Ops.begin()+Idx);
Ops.append(Mul->op_begin(), Mul->op_end());
DeletedMul = true;
}
- // If we deleted at least one mul, we added operands to the end of the list,
- // and they are not necessarily sorted. Recurse to resort and resimplify
- // any operands we just acquired.
+ // If we deleted at least one mul, we added operands to the end of the
+ // list, and they are not necessarily sorted. Recurse to resort and
+ // resimplify any operands we just acquired.
if (DeletedMul)
- return getMulExpr(Ops);
+ return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
}
// If there are any add recurrences in the operands list, see if any other
@@ -2784,8 +2818,8 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
// Scan over all recurrences, trying to fold loop invariants into them.
for (; Idx < Ops.size() && isa<SCEVAddRecExpr>(Ops[Idx]); ++Idx) {
- // Scan all of the other operands to this mul and add them to the vector if
- // they are loop invariant w.r.t. the recurrence.
+ // Scan all of the other operands to this mul and add them to the vector
+ // if they are loop invariant w.r.t. the recurrence.
SmallVector<const SCEV *, 8> LIOps;
const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
const Loop *AddRecLoop = AddRec->getLoop();
@@ -2801,9 +2835,10 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
// NLI * LI * {Start,+,Step} --> NLI * {LI*Start,+,LI*Step}
SmallVector<const SCEV *, 4> NewOps;
NewOps.reserve(AddRec->getNumOperands());
- const SCEV *Scale = getMulExpr(LIOps);
+ const SCEV *Scale = getMulExpr(LIOps, SCEV::FlagAnyWrap, Depth + 1);
for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i)
- NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i)));
+ NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i),
+ SCEV::FlagAnyWrap, Depth + 1));
// Build the new addrec. Propagate the NUW and NSW flags if both the
// outer mul and the inner addrec are guaranteed to have no overflow.
@@ -2822,12 +2857,12 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
Ops[i] = NewRec;
break;
}
- return getMulExpr(Ops);
+ return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
}
- // Okay, if there weren't any loop invariants to be folded, check to see if
- // there are multiple AddRec's with the same loop induction variable being
- // multiplied together. If so, we can fold them.
+ // Okay, if there weren't any loop invariants to be folded, check to see
+ // if there are multiple AddRec's with the same loop induction variable
+ // being multiplied together. If so, we can fold them.
// {A1,+,A2,+,...,+,An}<L> * {B1,+,B2,+,...,+,Bn}<L>
// = {x=1 in [ sum y=x..2x [ sum z=max(y-x, y-n)..min(x,n) [
@@ -2869,7 +2904,9 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
const SCEV *CoeffTerm = getConstant(Ty, Coeff);
const SCEV *Term1 = AddRec->getOperand(y-z);
const SCEV *Term2 = OtherAddRec->getOperand(z);
- Term = getAddExpr(Term, getMulExpr(CoeffTerm, Term1,Term2));
+ Term = getAddExpr(Term, getMulExpr(CoeffTerm, Term1, Term2,
+ SCEV::FlagAnyWrap, Depth + 1),
+ SCEV::FlagAnyWrap, Depth + 1);
}
}
AddRecOps.push_back(Term);
@@ -2887,7 +2924,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
}
}
if (OpsModified)
- return getMulExpr(Ops);
+ return getMulExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
// Otherwise couldn't fold anything into this recurrence. Move onto the
// next one.
@@ -2895,22 +2932,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
// Okay, it looks like we really DO need an mul expr. Check to see if we
// already have one, otherwise create a new one.
- FoldingSetNodeID ID;
- ID.AddInteger(scMulExpr);
- for (unsigned i = 0, e = Ops.size(); i != e; ++i)
- ID.AddPointer(Ops[i]);
- void *IP = nullptr;
- SCEVMulExpr *S =
- static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
- if (!S) {
- const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
- std::uninitialized_copy(Ops.begin(), Ops.end(), O);
- S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator),
- O, Ops.size());
- UniqueSCEVs.InsertNode(S, IP);
- }
- S->setNoWrapFlags(Flags);
- return S;
+ return getOrCreateMulExpr(Ops, Flags);
}
/// Get a canonical unsigned division expression, or something simpler if
@@ -3713,7 +3735,8 @@ const SCEV *ScalarEvolution::getNotSCEV(const SCEV *V) {
}
const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
- SCEV::NoWrapFlags Flags) {
+ SCEV::NoWrapFlags Flags,
+ unsigned Depth) {
// Fast path: X - X --> 0.
if (LHS == RHS)
return getZero(LHS->getType());
@@ -3747,7 +3770,7 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
// larger scope than intended.
auto NegFlags = RHSIsNotMinSigned ? SCEV::FlagNSW : SCEV::FlagAnyWrap;
- return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags);
+ return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags, Depth);
}
const SCEV *
diff --git a/lib/Analysis/TargetTransformInfo.cpp b/lib/Analysis/TargetTransformInfo.cpp
index 488cb332a0b0..92328f6e5efd 100644
--- a/lib/Analysis/TargetTransformInfo.cpp
+++ b/lib/Analysis/TargetTransformInfo.cpp
@@ -103,6 +103,10 @@ bool TargetTransformInfo::isSourceOfDivergence(const Value *V) const {
return TTIImpl->isSourceOfDivergence(V);
}
+bool llvm::TargetTransformInfo::isAlwaysUniform(const Value *V) const {
+ return TTIImpl->isAlwaysUniform(V);
+}
+
unsigned TargetTransformInfo::getFlatAddressSpace() const {
return TTIImpl->getFlatAddressSpace();
}
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index c0181662fd9d..b065f427b06c 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -852,7 +852,8 @@ static void computeKnownBitsFromShiftOperator(
Optional<bool> ShifterOperandIsNonZero;
// Early exit if we can't constrain any well-defined shift amount.
- if (!(ShiftAmtKZ & (BitWidth - 1)) && !(ShiftAmtKO & (BitWidth - 1))) {
+ if (!(ShiftAmtKZ & (PowerOf2Ceil(BitWidth) - 1)) &&
+ !(ShiftAmtKO & (PowerOf2Ceil(BitWidth) - 1))) {
ShifterOperandIsNonZero =
isKnownNonZero(I->getOperand(1), Depth + 1, Q);
if (!*ShifterOperandIsNonZero)
@@ -3026,7 +3027,7 @@ bool llvm::getConstantDataArrayInfo(const Value *V,
if (GV->getInitializer()->isNullValue()) {
Type *GVTy = GV->getValueType();
if ( (ArrayTy = dyn_cast<ArrayType>(GVTy)) ) {
- // A zeroinitializer for the array; There is no ConstantDataArray.
+ // A zeroinitializer for the array; there is no ConstantDataArray.
Array = nullptr;
} else {
const DataLayout &DL = GV->getParent()->getDataLayout();
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 95987fac74e1..0629c2d326ae 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -733,13 +733,13 @@ private:
std::vector<FunctionSummary::EdgeTy> makeCallList(ArrayRef<uint64_t> Record,
bool IsOldProfileFormat,
bool HasProfile);
- Error parseEntireSummary();
+ Error parseEntireSummary(unsigned ID);
Error parseModuleStringTable();
std::pair<ValueInfo, GlobalValue::GUID>
getValueInfoFromValueId(unsigned ValueId);
- ModulePathStringTableTy::iterator addThisModulePath();
+ ModuleSummaryIndex::ModuleInfo *addThisModule();
};
} // end anonymous namespace
@@ -2608,6 +2608,16 @@ Error BitcodeReader::materializeMetadata() {
if (Error Err = MDLoader->parseModuleMetadata())
return Err;
}
+
+ // Upgrade "Linker Options" module flag to "llvm.linker.options" module-level
+ // metadata.
+ if (Metadata *Val = TheModule->getModuleFlag("Linker Options")) {
+ NamedMDNode *LinkerOpts =
+ TheModule->getOrInsertNamedMetadata("llvm.linker.options");
+ for (const MDOperand &MDOptions : cast<MDNode>(Val)->operands())
+ LinkerOpts->addOperand(cast<MDNode>(MDOptions));
+ }
+
DeferredMetadataInfo.clear();
return Error::success();
}
@@ -4691,9 +4701,9 @@ ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
: BitcodeReaderBase(std::move(Cursor), Strtab), TheIndex(TheIndex),
ModulePath(ModulePath), ModuleId(ModuleId) {}
-ModulePathStringTableTy::iterator
-ModuleSummaryIndexBitcodeReader::addThisModulePath() {
- return TheIndex.addModulePath(ModulePath, ModuleId);
+ModuleSummaryIndex::ModuleInfo *
+ModuleSummaryIndexBitcodeReader::addThisModule() {
+ return TheIndex.addModule(ModulePath, ModuleId);
}
std::pair<ValueInfo, GlobalValue::GUID>
@@ -4844,6 +4854,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
return error("Invalid record");
break;
case bitc::GLOBALVAL_SUMMARY_BLOCK_ID:
+ case bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID:
assert(!SeenValueSymbolTable &&
"Already read VST when parsing summary block?");
// We might not have a VST if there were no values in the
@@ -4856,7 +4867,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
SeenValueSymbolTable = true;
}
SeenGlobalValSummary = true;
- if (Error Err = parseEntireSummary())
+ if (Error Err = parseEntireSummary(Entry.ID))
return Err;
break;
case bitc::MODULE_STRTAB_BLOCK_ID:
@@ -4889,7 +4900,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModule() {
case bitc::MODULE_CODE_HASH: {
if (Record.size() != 5)
return error("Invalid hash length " + Twine(Record.size()).str());
- auto &Hash = addThisModulePath()->second.second;
+ auto &Hash = addThisModule()->second.second;
int Pos = 0;
for (auto &Val : Record) {
assert(!(Val >> 32) && "Unexpected high bits set");
@@ -4964,8 +4975,8 @@ std::vector<FunctionSummary::EdgeTy> ModuleSummaryIndexBitcodeReader::makeCallLi
// Eagerly parse the entire summary block. This populates the GlobalValueSummary
// objects in the index.
-Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
- if (Stream.EnterSubBlock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID))
+Error ModuleSummaryIndexBitcodeReader::parseEntireSummary(unsigned ID) {
+ if (Stream.EnterSubBlock(ID))
return error("Invalid record");
SmallVector<uint64_t, 64> Record;
@@ -5070,7 +5081,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
PendingTypeTestAssumeConstVCalls.clear();
PendingTypeCheckedLoadConstVCalls.clear();
auto VIAndOriginalGUID = getValueInfoFromValueId(ValueID);
- FS->setModulePath(addThisModulePath()->first());
+ FS->setModulePath(addThisModule()->first());
FS->setOriginalName(VIAndOriginalGUID.second);
TheIndex.addGlobalValueSummary(VIAndOriginalGUID.first, std::move(FS));
break;
@@ -5090,7 +5101,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
// string table section in the per-module index, we create a single
// module path string table entry with an empty (0) ID to take
// ownership.
- AS->setModulePath(addThisModulePath()->first());
+ AS->setModulePath(addThisModule()->first());
GlobalValue::GUID AliaseeGUID =
getValueInfoFromValueId(AliaseeID).first.getGUID();
@@ -5113,7 +5124,7 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
std::vector<ValueInfo> Refs =
makeRefList(ArrayRef<uint64_t>(Record).slice(2));
auto FS = llvm::make_unique<GlobalVarSummary>(Flags, std::move(Refs));
- FS->setModulePath(addThisModulePath()->first());
+ FS->setModulePath(addThisModule()->first());
auto GUID = getValueInfoFromValueId(ValueID);
FS->setOriginalName(GUID.second);
TheIndex.addGlobalValueSummary(GUID.first, std::move(FS));
@@ -5241,6 +5252,20 @@ Error ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
{{Record[0], Record[1]}, {Record.begin() + 2, Record.end()}});
break;
}
+ case bitc::FS_CFI_FUNCTION_DEFS: {
+ std::set<std::string> &CfiFunctionDefs = TheIndex.cfiFunctionDefs();
+ for (unsigned I = 0; I != Record.size(); I += 2)
+ CfiFunctionDefs.insert(
+ {Strtab.data() + Record[I], static_cast<size_t>(Record[I + 1])});
+ break;
+ }
+ case bitc::FS_CFI_FUNCTION_DECLS: {
+ std::set<std::string> &CfiFunctionDecls = TheIndex.cfiFunctionDecls();
+ for (unsigned I = 0; I != Record.size(); I += 2)
+ CfiFunctionDecls.insert(
+ {Strtab.data() + Record[I], static_cast<size_t>(Record[I + 1])});
+ break;
+ }
}
}
llvm_unreachable("Exit infinite loop");
@@ -5255,7 +5280,7 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
SmallVector<uint64_t, 64> Record;
SmallString<128> ModulePath;
- ModulePathStringTableTy::iterator LastSeenModulePath;
+ ModuleSummaryIndex::ModuleInfo *LastSeenModule = nullptr;
while (true) {
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
@@ -5282,8 +5307,8 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
if (convertToString(Record, 1, ModulePath))
return error("Invalid record");
- LastSeenModulePath = TheIndex.addModulePath(ModulePath, ModuleId);
- ModuleIdMap[ModuleId] = LastSeenModulePath->first();
+ LastSeenModule = TheIndex.addModule(ModulePath, ModuleId);
+ ModuleIdMap[ModuleId] = LastSeenModule->first();
ModulePath.clear();
break;
@@ -5292,15 +5317,15 @@ Error ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
case bitc::MST_CODE_HASH: {
if (Record.size() != 5)
return error("Invalid hash length " + Twine(Record.size()).str());
- if (LastSeenModulePath == TheIndex.modulePaths().end())
+ if (!LastSeenModule)
return error("Invalid hash that does not follow a module path");
int Pos = 0;
for (auto &Val : Record) {
assert(!(Val >> 32) && "Unexpected high bits set");
- LastSeenModulePath->second.second[Pos++] = Val;
+ LastSeenModule->second.second[Pos++] = Val;
}
- // Reset LastSeenModulePath to avoid overriding the hash unexpectedly.
- LastSeenModulePath = TheIndex.modulePaths().end();
+ // Reset LastSeenModule to avoid overriding the hash unexpectedly.
+ LastSeenModule = nullptr;
break;
}
}
@@ -5507,13 +5532,16 @@ BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata,
}
// Parse the specified bitcode buffer and merge the index into CombinedIndex.
+// We don't use ModuleIdentifier here because the client may need to control the
+// module path used in the combined summary (e.g. when reading summaries for
+// regular LTO modules).
Error BitcodeModule::readSummary(ModuleSummaryIndex &CombinedIndex,
- unsigned ModuleId) {
+ StringRef ModulePath, uint64_t ModuleId) {
BitstreamCursor Stream(Buffer);
Stream.JumpToBit(ModuleBit);
ModuleSummaryIndexBitcodeReader R(std::move(Stream), Strtab, CombinedIndex,
- ModuleIdentifier, ModuleId);
+ ModulePath, ModuleId);
return R.parseModule();
}
@@ -5533,7 +5561,7 @@ Expected<std::unique_ptr<ModuleSummaryIndex>> BitcodeModule::getSummary() {
}
// Check if the given bitcode buffer contains a global value summary block.
-Expected<bool> BitcodeModule::hasSummary() {
+Expected<BitcodeLTOInfo> BitcodeModule::getLTOInfo() {
BitstreamCursor Stream(Buffer);
Stream.JumpToBit(ModuleBit);
@@ -5547,11 +5575,14 @@ Expected<bool> BitcodeModule::hasSummary() {
case BitstreamEntry::Error:
return error("Malformed block");
case BitstreamEntry::EndBlock:
- return false;
+ return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/false};
case BitstreamEntry::SubBlock:
if (Entry.ID == bitc::GLOBALVAL_SUMMARY_BLOCK_ID)
- return true;
+ return BitcodeLTOInfo{/*IsThinLTO=*/true, /*HasSummary=*/true};
+
+ if (Entry.ID == bitc::FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID)
+ return BitcodeLTOInfo{/*IsThinLTO=*/false, /*HasSummary=*/true};
// Ignore other sub-blocks.
if (Stream.SkipBlock())
@@ -5638,12 +5669,12 @@ Expected<std::string> llvm::getBitcodeProducerString(MemoryBufferRef Buffer) {
Error llvm::readModuleSummaryIndex(MemoryBufferRef Buffer,
ModuleSummaryIndex &CombinedIndex,
- unsigned ModuleId) {
+ uint64_t ModuleId) {
Expected<BitcodeModule> BM = getSingleModule(Buffer);
if (!BM)
return BM.takeError();
- return BM->readSummary(CombinedIndex, ModuleId);
+ return BM->readSummary(CombinedIndex, BM->getModuleIdentifier(), ModuleId);
}
Expected<std::unique_ptr<ModuleSummaryIndex>>
@@ -5655,12 +5686,12 @@ llvm::getModuleSummaryIndex(MemoryBufferRef Buffer) {
return BM->getSummary();
}
-Expected<bool> llvm::hasGlobalValueSummary(MemoryBufferRef Buffer) {
+Expected<BitcodeLTOInfo> llvm::getBitcodeLTOInfo(MemoryBufferRef Buffer) {
Expected<BitcodeModule> BM = getSingleModule(Buffer);
if (!BM)
return BM.takeError();
- return BM->hasSummary();
+ return BM->getLTOInfo();
}
Expected<std::unique_ptr<ModuleSummaryIndex>>
diff --git a/lib/Bitcode/Reader/MetadataLoader.cpp b/lib/Bitcode/Reader/MetadataLoader.cpp
index ee2fe2a0cc18..b1504a8034e0 100644
--- a/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -407,6 +407,11 @@ void PlaceholderQueue::flush(BitcodeReaderMetadataList &MetadataList) {
} // anonynous namespace
+static Error error(const Twine &Message) {
+ return make_error<StringError>(
+ Message, make_error_code(BitcodeError::CorruptedBitcode));
+}
+
class MetadataLoader::MetadataLoaderImpl {
BitcodeReaderMetadataList MetadataList;
BitcodeReaderValueList &ValueList;
@@ -533,6 +538,88 @@ class MetadataLoader::MetadataLoaderImpl {
}
}
+ /// Upgrade the expression from previous versions.
+ Error upgradeDIExpression(uint64_t FromVersion,
+ MutableArrayRef<uint64_t> &Expr,
+ SmallVectorImpl<uint64_t> &Buffer) {
+ auto N = Expr.size();
+ switch (FromVersion) {
+ default:
+ return error("Invalid record");
+ case 0:
+ if (N >= 3 && Expr[N - 3] == dwarf::DW_OP_bit_piece)
+ Expr[N - 3] = dwarf::DW_OP_LLVM_fragment;
+ LLVM_FALLTHROUGH;
+ case 1:
+ // Move DW_OP_deref to the end.
+ if (N && Expr[0] == dwarf::DW_OP_deref) {
+ auto End = Expr.end();
+ if (Expr.size() >= 3 &&
+ *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
+ End = std::prev(End, 3);
+ std::move(std::next(Expr.begin()), End, Expr.begin());
+ *std::prev(End) = dwarf::DW_OP_deref;
+ }
+ NeedDeclareExpressionUpgrade = true;
+ LLVM_FALLTHROUGH;
+ case 2: {
+ // Change DW_OP_plus to DW_OP_plus_uconst.
+ // Change DW_OP_minus to DW_OP_uconst, DW_OP_minus
+ auto SubExpr = ArrayRef<uint64_t>(Expr);
+ while (!SubExpr.empty()) {
+ // Skip past other operators with their operands
+ // for this version of the IR, obtained from
+ // from historic DIExpression::ExprOperand::getSize().
+ size_t HistoricSize;
+ switch (SubExpr.front()) {
+ default:
+ HistoricSize = 1;
+ break;
+ case dwarf::DW_OP_constu:
+ case dwarf::DW_OP_minus:
+ case dwarf::DW_OP_plus:
+ HistoricSize = 2;
+ break;
+ case dwarf::DW_OP_LLVM_fragment:
+ HistoricSize = 3;
+ break;
+ }
+
+ // If the expression is malformed, make sure we don't
+ // copy more elements than we should.
+ HistoricSize = std::min(SubExpr.size(), HistoricSize);
+ ArrayRef<uint64_t> Args = SubExpr.slice(1, HistoricSize-1);
+
+ switch (SubExpr.front()) {
+ case dwarf::DW_OP_plus:
+ Buffer.push_back(dwarf::DW_OP_plus_uconst);
+ Buffer.append(Args.begin(), Args.end());
+ break;
+ case dwarf::DW_OP_minus:
+ Buffer.push_back(dwarf::DW_OP_constu);
+ Buffer.append(Args.begin(), Args.end());
+ Buffer.push_back(dwarf::DW_OP_minus);
+ break;
+ default:
+ Buffer.push_back(*SubExpr.begin());
+ Buffer.append(Args.begin(), Args.end());
+ break;
+ }
+
+ // Continue with remaining elements.
+ SubExpr = SubExpr.slice(HistoricSize);
+ }
+ Expr = MutableArrayRef<uint64_t>(Buffer);
+ LLVM_FALLTHROUGH;
+ }
+ case 3:
+ // Up-to-date!
+ break;
+ }
+
+ return Error::success();
+ }
+
void upgradeDebugInfo() {
upgradeCUSubprograms();
upgradeCUVariables();
@@ -590,11 +677,6 @@ public:
void upgradeDebugIntrinsics(Function &F) { upgradeDeclareExpressions(F); }
};
-static Error error(const Twine &Message) {
- return make_error<StringError>(
- Message, make_error_code(BitcodeError::CorruptedBitcode));
-}
-
Expected<bool>
MetadataLoader::MetadataLoaderImpl::lazyLoadModuleMetadataBlock() {
IndexCursor = Stream;
@@ -1551,34 +1633,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
IsDistinct = Record[0] & 1;
uint64_t Version = Record[0] >> 1;
auto Elts = MutableArrayRef<uint64_t>(Record).slice(1);
- unsigned N = Elts.size();
- // Perform various upgrades.
- switch (Version) {
- case 0:
- if (N >= 3 && Elts[N - 3] == dwarf::DW_OP_bit_piece)
- Elts[N - 3] = dwarf::DW_OP_LLVM_fragment;
- LLVM_FALLTHROUGH;
- case 1:
- // Move DW_OP_deref to the end.
- if (N && Elts[0] == dwarf::DW_OP_deref) {
- auto End = Elts.end();
- if (Elts.size() >= 3 && *std::prev(End, 3) == dwarf::DW_OP_LLVM_fragment)
- End = std::prev(End, 3);
- std::move(std::next(Elts.begin()), End, Elts.begin());
- *std::prev(End) = dwarf::DW_OP_deref;
- }
- NeedDeclareExpressionUpgrade = true;
- LLVM_FALLTHROUGH;
- case 2:
- // Up-to-date!
- break;
- default:
- return error("Invalid record");
- }
+
+ SmallVector<uint64_t, 6> Buffer;
+ if (Error Err = upgradeDIExpression(Version, Elts, Buffer))
+ return Err;
MetadataList.assignValue(
- GET_OR_DISTINCT(DIExpression, (Context, makeArrayRef(Record).slice(1))),
- NextMetadataNo);
+ GET_OR_DISTINCT(DIExpression, (Context, Elts)), NextMetadataNo);
NextMetadataNo++;
break;
}
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index d5879fec95cb..feeba31908ae 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -77,10 +77,13 @@ protected:
/// The stream created and owned by the client.
BitstreamWriter &Stream;
+ StringTableBuilder &StrtabBuilder;
+
public:
/// Constructs a BitcodeWriterBase object that writes to the provided
/// \p Stream.
- BitcodeWriterBase(BitstreamWriter &Stream) : Stream(Stream) {}
+ BitcodeWriterBase(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder)
+ : Stream(Stream), StrtabBuilder(StrtabBuilder) {}
protected:
void writeBitcodeHeader();
@@ -97,8 +100,6 @@ class ModuleBitcodeWriter : public BitcodeWriterBase {
/// Pointer to the buffer allocated by caller for bitcode writing.
const SmallVectorImpl<char> &Buffer;
- StringTableBuilder &StrtabBuilder;
-
/// The Module to write to bitcode.
const Module &M;
@@ -142,8 +143,8 @@ public:
BitstreamWriter &Stream, bool ShouldPreserveUseListOrder,
const ModuleSummaryIndex *Index, bool GenerateHash,
ModuleHash *ModHash = nullptr)
- : BitcodeWriterBase(Stream), Buffer(Buffer), StrtabBuilder(StrtabBuilder),
- M(*M), VE(*M, ShouldPreserveUseListOrder), Index(Index),
+ : BitcodeWriterBase(Stream, StrtabBuilder), Buffer(Buffer), M(*M),
+ VE(*M, ShouldPreserveUseListOrder), Index(Index),
GenerateHash(GenerateHash), ModHash(ModHash),
BitcodeStartBit(Stream.GetCurrentBitNo()) {
// Assign ValueIds to any callee values in the index that came from
@@ -331,10 +332,11 @@ public:
/// Constructs a IndexBitcodeWriter object for the given combined index,
/// writing to the provided \p Buffer. When writing a subset of the index
/// for a distributed backend, provide a \p ModuleToSummariesForIndex map.
- IndexBitcodeWriter(BitstreamWriter &Stream, const ModuleSummaryIndex &Index,
+ IndexBitcodeWriter(BitstreamWriter &Stream, StringTableBuilder &StrtabBuilder,
+ const ModuleSummaryIndex &Index,
const std::map<std::string, GVSummaryMapTy>
*ModuleToSummariesForIndex = nullptr)
- : BitcodeWriterBase(Stream), Index(Index),
+ : BitcodeWriterBase(Stream, StrtabBuilder), Index(Index),
ModuleToSummariesForIndex(ModuleToSummariesForIndex) {
// Assign unique value ids to all summaries to be written, for use
// in writing out the call graph edges. Save the mapping from GUID
@@ -1663,7 +1665,7 @@ void ModuleBitcodeWriter::writeDIExpression(const DIExpression *N,
SmallVectorImpl<uint64_t> &Record,
unsigned Abbrev) {
Record.reserve(N->getElements().size() + 1);
- const uint64_t Version = 2 << 1;
+ const uint64_t Version = 3 << 1;
Record.push_back((uint64_t)N->isDistinct() | Version);
Record.append(N->elements_begin(), N->elements_end());
@@ -3595,6 +3597,24 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
MaybeEmitOriginalName(*AS);
}
+ if (!Index.cfiFunctionDefs().empty()) {
+ for (auto &S : Index.cfiFunctionDefs()) {
+ NameVals.push_back(StrtabBuilder.add(S));
+ NameVals.push_back(S.size());
+ }
+ Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DEFS, NameVals);
+ NameVals.clear();
+ }
+
+ if (!Index.cfiFunctionDecls().empty()) {
+ for (auto &S : Index.cfiFunctionDecls()) {
+ NameVals.push_back(StrtabBuilder.add(S));
+ NameVals.push_back(S.size());
+ }
+ Stream.EmitRecord(bitc::FS_CFI_FUNCTION_DECLS, NameVals);
+ NameVals.clear();
+ }
+
Stream.ExitBlock();
}
@@ -3829,6 +3849,14 @@ void BitcodeWriter::writeModule(const Module *M,
ModuleWriter.write();
}
+void BitcodeWriter::writeIndex(
+ const ModuleSummaryIndex *Index,
+ const std::map<std::string, GVSummaryMapTy> *ModuleToSummariesForIndex) {
+ IndexBitcodeWriter IndexWriter(*Stream, StrtabBuilder, *Index,
+ ModuleToSummariesForIndex);
+ IndexWriter.write();
+}
+
/// WriteBitcodeToFile - Write the specified module to the specified output
/// stream.
void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
@@ -3880,11 +3908,9 @@ void llvm::WriteIndexToFile(
SmallVector<char, 0> Buffer;
Buffer.reserve(256 * 1024);
- BitstreamWriter Stream(Buffer);
- writeBitcodeHeader(Stream);
-
- IndexBitcodeWriter IndexWriter(Stream, Index, ModuleToSummariesForIndex);
- IndexWriter.write();
+ BitcodeWriter Writer(Buffer);
+ Writer.writeIndex(&Index, ModuleToSummariesForIndex);
+ Writer.writeStrtab();
Out.write((char *)&Buffer.front(), Buffer.size());
}
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index f7c09be15fb7..946067e6358f 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -24,3 +24,4 @@ add_subdirectory(Fuzzer)
add_subdirectory(Passes)
add_subdirectory(ToolDrivers)
add_subdirectory(XRay)
+add_subdirectory(Testing)
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 407d5623d670..ad348d723bae 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1286,11 +1286,7 @@ bool AsmPrinter::doFinalization(Module &M) {
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
- // Emit module flags.
- SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
- M.getModuleFlagsMetadata(ModuleFlags);
- if (!ModuleFlags.empty())
- TLOF.emitModuleFlags(*OutStreamer, ModuleFlags, TM);
+ TLOF.emitModuleMetadata(*OutStreamer, M, TM);
if (TM.getTargetTriple().isOSBinFormatELF()) {
MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 04073b3aed68..dc39d1e6cb52 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -552,7 +552,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
int Offset = TFI->getFrameIndexReference(*Asm->MF, Fragment.FI, FrameReg);
DwarfExpr.addFragmentOffset(Expr);
SmallVector<uint64_t, 8> Ops;
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Offset);
Ops.append(Expr->elements_begin(), Expr->elements_end());
DIExpressionCursor Cursor(Ops);
@@ -821,7 +821,7 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
DIExpressionCursor Cursor(Ops);
@@ -850,7 +850,7 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index e3fd21a1fd70..75eb355bfb54 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1511,7 +1511,7 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
DwarfExpr.setMemoryLocationKind();
SmallVector<uint64_t, 8> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
Ops.append(DIExpr->elements_begin(), DIExpr->elements_end());
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index ebfba4cfc275..5dfe06c64ec2 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -134,6 +134,13 @@ public:
assert(!FrameIndexExprs.empty() && "Expected an MMI entry");
assert(!V.FrameIndexExprs.empty() && "Expected an MMI entry");
+ if (FrameIndexExprs.size()) {
+ auto *Expr = FrameIndexExprs.back().Expr;
+ // Get rid of duplicate non-fragment entries. More than one non-fragment
+ // dbg.declare makes no sense so ignore all but the first.
+ if (!Expr || !Expr->isFragment())
+ return;
+ }
FrameIndexExprs.append(V.FrameIndexExprs.begin(), V.FrameIndexExprs.end());
assert(all_of(FrameIndexExprs,
[](FrameIndexExpr &FIE) {
diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index d96479f43433..fe38ee805682 100644
--- a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -248,15 +248,25 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
assert(Reg.Size == 0 && "subregister has same size as superregister");
// Pattern-match combinations for which more efficient representations exist.
- // [Reg, Offset, DW_OP_plus] --> [DW_OP_breg, Offset].
- // [Reg, Offset, DW_OP_minus] --> [DW_OP_breg, -Offset].
- // If Reg is a subregister we need to mask it out before subtracting.
- if (Op && ((Op->getOp() == dwarf::DW_OP_plus) ||
- (Op->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
- int Offset = Op->getArg(0);
- SignedOffset = (Op->getOp() == dwarf::DW_OP_plus) ? Offset : -Offset;
+ // [Reg, DW_OP_plus_uconst, Offset] --> [DW_OP_breg, Offset].
+ if (Op && (Op->getOp() == dwarf::DW_OP_plus_uconst)) {
+ SignedOffset = Op->getArg(0);
ExprCursor.take();
}
+
+ // [Reg, DW_OP_constu, Offset, DW_OP_plus] --> [DW_OP_breg, Offset]
+ // [Reg, DW_OP_constu, Offset, DW_OP_minus] --> [DW_OP_breg,-Offset]
+ // If Reg is a subregister we need to mask it out before subtracting.
+ if (Op && Op->getOp() == dwarf::DW_OP_constu) {
+ auto N = ExprCursor.peekNext();
+ if (N && (N->getOp() == dwarf::DW_OP_plus ||
+ (N->getOp() == dwarf::DW_OP_minus && !SubRegisterSizeInBits))) {
+ int Offset = Op->getArg(0);
+ SignedOffset = (N->getOp() == dwarf::DW_OP_minus) ? -Offset : Offset;
+ ExprCursor.consume(2);
+ }
+ }
+
if (FBReg)
addFBReg(SignedOffset);
else
@@ -320,17 +330,14 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
LocationKind = Unknown;
return;
}
- case dwarf::DW_OP_plus:
+ case dwarf::DW_OP_plus_uconst:
assert(LocationKind != Register);
emitOp(dwarf::DW_OP_plus_uconst);
emitUnsigned(Op->getArg(0));
break;
+ case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus:
- assert(LocationKind != Register);
- // There is no DW_OP_minus_uconst.
- emitOp(dwarf::DW_OP_constu);
- emitUnsigned(Op->getArg(0));
- emitOp(dwarf::DW_OP_minus);
+ emitOp(Op->getOp());
break;
case dwarf::DW_OP_deref: {
assert(LocationKind != Register);
diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.h b/lib/CodeGen/AsmPrinter/DwarfExpression.h
index de8613200067..728f8ad9225b 100644
--- a/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -42,6 +42,9 @@ public:
DIExpressionCursor(ArrayRef<uint64_t> Expr)
: Start(Expr.begin()), End(Expr.end()) {}
+ DIExpressionCursor(const DIExpressionCursor &C)
+ : Start(C.Start), End(C.End) {}
+
/// Consume one operation.
Optional<DIExpression::ExprOperand> take() {
if (Start == End)
diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 7f7d3e650e02..708f5f7536ff 100644
--- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -475,7 +475,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
SmallVector<uint64_t, 9> Ops;
if (Location.isIndirect() && Location.getOffset()) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Location.getOffset());
}
// If we started with a pointer to the __Block_byref... struct, then
@@ -487,7 +487,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
// DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in
// adding the offset if it's 0.
if (forwardingFieldOffset > 0) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(forwardingFieldOffset);
}
@@ -499,7 +499,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
// for the variable's field to get to the location of the actual variable:
// DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0.
if (varFieldOffset > 0) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(varFieldOffset);
}
diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp
index c2037cb7f1ae..37e176099ea7 100644
--- a/lib/CodeGen/CodeGenPrepare.cpp
+++ b/lib/CodeGen/CodeGenPrepare.cpp
@@ -134,7 +134,7 @@ static cl::opt<bool> DisablePreheaderProtect(
cl::desc("Disable protection against removing loop preheaders"));
static cl::opt<bool> ProfileGuidedSectionPrefix(
- "profile-guided-section-prefix", cl::Hidden, cl::init(true),
+ "profile-guided-section-prefix", cl::Hidden, cl::init(true), cl::ZeroOrMore,
cl::desc("Use profile info to add section prefix for hot/cold functions"));
static cl::opt<unsigned> FreqRatioToSkipMerge(
diff --git a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index ef5818dabe23..1d0d3dffa4c5 100644
--- a/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -82,6 +82,12 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
case TargetOpcode::G_UDIV:
assert(Size == 32 && "Unsupported size");
return RTLIB::UDIV_I32;
+ case TargetOpcode::G_SREM:
+ assert(Size == 32 && "Unsupported size");
+ return RTLIB::SREM_I32;
+ case TargetOpcode::G_UREM:
+ assert(Size == 32 && "Unsupported size");
+ return RTLIB::UREM_I32;
case TargetOpcode::G_FADD:
assert((Size == 32 || Size == 64) && "Unsupported size");
return Size == 64 ? RTLIB::ADD_F64 : RTLIB::ADD_F32;
@@ -93,43 +99,57 @@ static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
llvm_unreachable("Unknown libcall function");
}
-static LegalizerHelper::LegalizeResult
-simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
- Type *OpType) {
+LegalizerHelper::LegalizeResult llvm::replaceWithLibcall(
+ MachineInstr &MI, MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
+ const CallLowering::ArgInfo &Result, ArrayRef<CallLowering::ArgInfo> Args) {
auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
auto &TLI = *MIRBuilder.getMF().getSubtarget().getTargetLowering();
- auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
const char *Name = TLI.getLibcallName(Libcall);
MIRBuilder.getMF().getFrameInfo().setHasCalls(true);
- CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
- MachineOperand::CreateES(Name),
- {MI.getOperand(0).getReg(), OpType},
- {{MI.getOperand(1).getReg(), OpType},
- {MI.getOperand(2).getReg(), OpType}});
+ MIRBuilder.setInstr(MI);
+ if (!CLI.lowerCall(MIRBuilder, TLI.getLibcallCallingConv(Libcall),
+ MachineOperand::CreateES(Name), Result, Args))
+ return LegalizerHelper::UnableToLegalize;
+
+ // We're about to remove MI, so move the insert point after it.
+ MIRBuilder.setInsertPt(MIRBuilder.getMBB(),
+ std::next(MIRBuilder.getInsertPt()));
+
MI.eraseFromParent();
return LegalizerHelper::Legalized;
}
+static LegalizerHelper::LegalizeResult
+simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size,
+ Type *OpType) {
+ auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
+ return replaceWithLibcall(MI, MIRBuilder, Libcall,
+ {MI.getOperand(0).getReg(), OpType},
+ {{MI.getOperand(1).getReg(), OpType},
+ {MI.getOperand(2).getReg(), OpType}});
+}
+
LegalizerHelper::LegalizeResult
LegalizerHelper::libcall(MachineInstr &MI) {
- LLT Ty = MRI.getType(MI.getOperand(0).getReg());
- unsigned Size = Ty.getSizeInBits();
+ LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
+ unsigned Size = LLTy.getSizeInBits();
auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
- MIRBuilder.setInstr(MI);
switch (MI.getOpcode()) {
default:
return UnableToLegalize;
case TargetOpcode::G_SDIV:
- case TargetOpcode::G_UDIV: {
- Type *Ty = Type::getInt32Ty(Ctx);
- return simpleLibcall(MI, MIRBuilder, Size, Ty);
+ case TargetOpcode::G_UDIV:
+ case TargetOpcode::G_SREM:
+ case TargetOpcode::G_UREM: {
+ Type *HLTy = Type::getInt32Ty(Ctx);
+ return simpleLibcall(MI, MIRBuilder, Size, HLTy);
}
case TargetOpcode::G_FADD:
case TargetOpcode::G_FPOW:
case TargetOpcode::G_FREM: {
- Type *Ty = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
- return simpleLibcall(MI, MIRBuilder, Size, Ty);
+ Type *HLTy = Size == 64 ? Type::getDoubleTy(Ctx) : Type::getFloatTy(Ctx);
+ return simpleLibcall(MI, MIRBuilder, Size, HLTy);
}
}
}
@@ -237,17 +257,18 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
unsigned NarrowSize = NarrowTy.getSizeInBits();
int NumParts =
MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
- LLT NarrowPtrTy = LLT::pointer(
- MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
+ LLT OffsetTy = LLT::scalar(
+ MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
SmallVector<unsigned, 2> DstRegs;
for (int i = 0; i < NumParts; ++i) {
unsigned DstReg = MRI.createGenericVirtualRegister(NarrowTy);
- unsigned SrcReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
- unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
+ unsigned SrcReg = 0;
+ unsigned Adjustment = i * NarrowSize / 8;
+
+ MIRBuilder.materializeGEP(SrcReg, MI.getOperand(1).getReg(), OffsetTy,
+ Adjustment);
- MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
- MIRBuilder.buildGEP(SrcReg, MI.getOperand(1).getReg(), Offset);
// TODO: This is conservatively correct, but we probably want to split the
// memory operands in the future.
MIRBuilder.buildLoad(DstReg, SrcReg, **MI.memoperands_begin());
@@ -263,17 +284,19 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
unsigned NarrowSize = NarrowTy.getSizeInBits();
int NumParts =
MRI.getType(MI.getOperand(0).getReg()).getSizeInBits() / NarrowSize;
- LLT NarrowPtrTy = LLT::pointer(
- MRI.getType(MI.getOperand(1).getReg()).getAddressSpace(), NarrowSize);
+ LLT OffsetTy = LLT::scalar(
+ MRI.getType(MI.getOperand(1).getReg()).getScalarSizeInBits());
SmallVector<unsigned, 2> SrcRegs;
extractParts(MI.getOperand(0).getReg(), NarrowTy, NumParts, SrcRegs);
for (int i = 0; i < NumParts; ++i) {
- unsigned DstReg = MRI.createGenericVirtualRegister(NarrowPtrTy);
- unsigned Offset = MRI.createGenericVirtualRegister(LLT::scalar(64));
- MIRBuilder.buildConstant(Offset, i * NarrowSize / 8);
- MIRBuilder.buildGEP(DstReg, MI.getOperand(1).getReg(), Offset);
+ unsigned DstReg = 0;
+ unsigned Adjustment = i * NarrowSize / 8;
+
+ MIRBuilder.materializeGEP(DstReg, MI.getOperand(1).getReg(), OffsetTy,
+ Adjustment);
+
// TODO: This is conservatively correct, but we probably want to split the
// memory operands in the future.
MIRBuilder.buildStore(SrcRegs[i], DstReg, **MI.memoperands_begin());
diff --git a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index 54ef7e5c5a1b..79d312fb52ca 100644
--- a/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -191,6 +191,24 @@ MachineInstrBuilder MachineIRBuilder::buildGEP(unsigned Res, unsigned Op0,
.addUse(Op1);
}
+Optional<MachineInstrBuilder>
+MachineIRBuilder::materializeGEP(unsigned &Res, unsigned Op0,
+ const LLT &ValueTy, uint64_t Value) {
+ assert(Res == 0 && "Res is a result argument");
+ assert(ValueTy.isScalar() && "invalid offset type");
+
+ if (Value == 0) {
+ Res = Op0;
+ return None;
+ }
+
+ Res = MRI->createGenericVirtualRegister(MRI->getType(Op0));
+ unsigned TmpReg = MRI->createGenericVirtualRegister(ValueTy);
+
+ buildConstant(TmpReg, Value);
+ return buildGEP(Res, Op0, TmpReg);
+}
+
MachineInstrBuilder MachineIRBuilder::buildPtrMask(unsigned Res, unsigned Op0,
uint32_t NumBits) {
assert(MRI->getType(Res).isPointer() &&
diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp
index fc52b0da0d61..2d4b95974cc6 100644
--- a/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/lib/CodeGen/MachineBlockPlacement.cpp
@@ -594,8 +594,8 @@ BranchProbability MachineBlockPlacement::collectViableSuccessors(
// Assume A->C is very hot (>90%), and C->D has a 50% probability, then after
// A->C is chosen as a fall-through, D won't be selected as a successor of C
// due to CFG constraint (the probability of C->D is not greater than
- // HotProb to break top-order). If we exclude E that is not in BlockFilter
- // when calculating the probability of C->D, D will be selected and we
+ // HotProb to break topo-order). If we exclude E that is not in BlockFilter
+ // when calculating the probability of C->D, D will be selected and we
// will get A C D B as the layout of this loop.
auto AdjustedSumProb = BranchProbability::getOne();
for (MachineBasicBlock *Succ : BB->successors()) {
@@ -1156,7 +1156,7 @@ void MachineBlockPlacement::precomputeTriangleChains() {
continue;
// Now we have an interesting triangle. Insert it if it's not part of an
- // existing chain
+ // existing chain.
// Note: This cannot be replaced with a call insert() or emplace() because
// the find key is BB, but the insert/emplace key is PDom.
auto Found = TriangleChainMap.find(&BB);
@@ -1298,9 +1298,9 @@ bool MachineBlockPlacement::hasBetterLayoutPredecessor(
// | | | |
// ---BB | | BB
// | | | |
- // | pred-- | Succ--
+ // | Pred-- | Succ--
// | | | |
- // ---succ ---pred--
+ // ---Succ ---Pred--
//
// cost = freq(S->Pred) + freq(BB->Succ) cost = 2 * freq (S->Pred)
// = freq(S->Pred) + freq(S->BB)
diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp
index 52d5819f8dbc..c7113f1fdc47 100644
--- a/lib/CodeGen/MachineLICM.cpp
+++ b/lib/CodeGen/MachineLICM.cpp
@@ -895,8 +895,11 @@ bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) {
// If the physreg has no defs anywhere, it's just an ambient register
// and we can freely move its uses. Alternatively, if it's allocatable,
// it could get allocated to something with a def during allocation.
- if (!MRI->isConstantPhysReg(Reg))
- return false;
+ // However, if the physreg is known to always be caller saved/restored
+ // then this use is safe to hoist.
+ if (!MRI->isConstantPhysReg(Reg) &&
+ !(TRI->isCallerPreservedPhysReg(Reg, *I.getParent()->getParent())))
+ return false;
// Otherwise it's safe to move.
continue;
} else if (!MO.isDead()) {
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index a0967f574006..2d4422d94a17 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2217,7 +2217,8 @@ SDValue DAGCombiner::visitADDCARRYLike(SDValue N0, SDValue N1, SDValue CarryIn,
SDNode *N) {
// Iff the flag result is dead:
// (addcarry (add|uaddo X, Y), 0, Carry) -> (addcarry X, Y, Carry)
- if ((N0.getOpcode() == ISD::ADD || N0.getOpcode() == ISD::UADDO) &&
+ if ((N0.getOpcode() == ISD::ADD ||
+ (N0.getOpcode() == ISD::UADDO && N0.getResNo() == 0)) &&
isNullConstant(N1) && !N->hasAnyUseOfValue(1))
return DAG.getNode(ISD::ADDCARRY, SDLoc(N), N->getVTList(),
N0.getOperand(0), N0.getOperand(1), CarryIn);
@@ -12460,10 +12461,27 @@ bool DAGCombiner::MergeStoresOfConstantsOrVecElts(
LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
SDValue NewChain = getMergeStoreChains(StoreNodes, NumStores);
- SDValue NewStore = DAG.getStore(NewChain, DL, StoredVal,
- FirstInChain->getBasePtr(),
- FirstInChain->getPointerInfo(),
- FirstInChain->getAlignment());
+
+ // make sure we use trunc store if it's necessary to be legal.
+ SDValue NewStore;
+ if (TLI.isTypeLegal(StoredVal.getValueType())) {
+ NewStore = DAG.getStore(NewChain, DL, StoredVal, FirstInChain->getBasePtr(),
+ FirstInChain->getPointerInfo(),
+ FirstInChain->getAlignment());
+ } else { // Must be realized as a trunc store
+ EVT LegalizedStoredValueTy =
+ TLI.getTypeToTransformTo(*DAG.getContext(), StoredVal.getValueType());
+ unsigned LegalizedStoreSize = LegalizedStoredValueTy.getSizeInBits();
+ ConstantSDNode *C = cast<ConstantSDNode>(StoredVal);
+ SDValue ExtendedStoreVal =
+ DAG.getConstant(C->getAPIntValue().zextOrTrunc(LegalizedStoreSize), DL,
+ LegalizedStoredValueTy);
+ NewStore = DAG.getTruncStore(
+ NewChain, DL, ExtendedStoreVal, FirstInChain->getBasePtr(),
+ FirstInChain->getPointerInfo(), StoredVal.getValueType() /*TVT*/,
+ FirstInChain->getAlignment(),
+ FirstInChain->getMemOperand()->getFlags());
+ }
// Replace all merged stores with the new store.
for (unsigned i = 0; i < NumStores; ++i)
@@ -12731,8 +12749,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
IsFast) {
LastLegalType = i + 1;
// Or check whether a truncstore is legal.
- } else if (!LegalTypes &&
- TLI.getTypeAction(Context, StoreTy) ==
+ } else if (TLI.getTypeAction(Context, StoreTy) ==
TargetLowering::TypePromoteInteger) {
EVT LegalizedStoredValueTy =
TLI.getTypeToTransformTo(Context, StoredVal.getValueType());
@@ -12947,8 +12964,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
else if (TLI.getTypeAction(Context, StoreTy) ==
TargetLowering::TypePromoteInteger) {
EVT LegalizedStoredValueTy = TLI.getTypeToTransformTo(Context, StoreTy);
- if (!LegalTypes &&
- TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) &&
+ if (TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) &&
TLI.canMergeStoresTo(FirstStoreAS, LegalizedStoredValueTy) &&
TLI.isLoadExtLegal(ISD::ZEXTLOAD, LegalizedStoredValueTy,
StoreTy) &&
@@ -12958,8 +12974,8 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy,
FirstStoreAS, FirstStoreAlign, &IsFastSt) &&
IsFastSt &&
- TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy,
- FirstLoadAS, FirstLoadAlign, &IsFastLd) &&
+ TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstLoadAS,
+ FirstLoadAlign, &IsFastLd) &&
IsFastLd)
LastLegalIntegerType = i + 1;
}
@@ -13189,10 +13205,6 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
Chain = ST->getChain();
}
- // Try transforming N to an indexed store.
- if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N))
- return SDValue(N, 0);
-
// FIXME: is there such a thing as a truncating indexed store?
if (ST->isTruncatingStore() && ST->isUnindexed() &&
Value.getValueType().isInteger()) {
@@ -13287,6 +13299,10 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) {
}
}
+ // Try transforming N to an indexed store.
+ if (CombineToPreIndexedLoadStore(N) || CombineToPostIndexedLoadStore(N))
+ return SDValue(N, 0);
+
// Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr'
//
// Make sure to do this only after attempting to merge stores in order to
@@ -14692,21 +14708,7 @@ static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG) {
MachineMemOperand *MMO = MF.getMachineMemOperand(Ld->getMemOperand(), Offset,
VT.getStoreSize());
SDValue NewLd = DAG.getLoad(VT, DL, Ld->getChain(), NewAddr, MMO);
-
- // The new load must have the same position as the old load in terms of memory
- // dependency. Create a TokenFactor for Ld and NewLd and update uses of Ld's
- // output chain to use that TokenFactor.
- // TODO: This code is based on a similar sequence in x86 lowering. It should
- // be moved to a helper function, so it can be shared and reused.
- if (Ld->hasAnyUseOfValue(1)) {
- SDValue OldChain = SDValue(Ld, 1);
- SDValue NewChain = SDValue(NewLd.getNode(), 1);
- SDValue TokenFactor = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
- OldChain, NewChain);
- DAG.ReplaceAllUsesOfValueWith(OldChain, TokenFactor);
- DAG.UpdateNodeOperands(TokenFactor.getNode(), OldChain, NewChain);
- }
-
+ DAG.makeEquivalentMemoryOrdering(Ld, NewLd);
return NewLd;
}
diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index 606b8952f3c1..b736037d71dd 100644
--- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -523,3 +523,29 @@ void FunctionLoweringInfo::setCurrentSwiftErrorVReg(
const MachineBasicBlock *MBB, const Value *Val, unsigned VReg) {
SwiftErrorVRegDefMap[std::make_pair(MBB, Val)] = VReg;
}
+
+std::pair<unsigned, bool>
+FunctionLoweringInfo::getOrCreateSwiftErrorVRegDefAt(const Instruction *I) {
+ auto Key = PointerIntPair<const Instruction *, 1, bool>(I, true);
+ auto It = SwiftErrorVRegDefUses.find(Key);
+ if (It == SwiftErrorVRegDefUses.end()) {
+ auto &DL = MF->getDataLayout();
+ const TargetRegisterClass *RC = TLI->getRegClassFor(TLI->getPointerTy(DL));
+ unsigned VReg = MF->getRegInfo().createVirtualRegister(RC);
+ SwiftErrorVRegDefUses[Key] = VReg;
+ return std::make_pair(VReg, true);
+ }
+ return std::make_pair(It->second, false);
+}
+
+std::pair<unsigned, bool>
+FunctionLoweringInfo::getOrCreateSwiftErrorVRegUseAt(const Instruction *I, const MachineBasicBlock *MBB, const Value *Val) {
+ auto Key = PointerIntPair<const Instruction *, 1, bool>(I, false);
+ auto It = SwiftErrorVRegDefUses.find(Key);
+ if (It == SwiftErrorVRegDefUses.end()) {
+ unsigned VReg = getOrCreateSwiftErrorVReg(MBB, Val);
+ SwiftErrorVRegDefUses[Key] = VReg;
+ return std::make_pair(VReg, true);
+ }
+ return std::make_pair(It->second, false);
+}
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index e54eaa3b81be..15e87b7af18d 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2192,19 +2192,6 @@ static bool isSinCosLibcallAvailable(SDNode *Node, const TargetLowering &TLI) {
return TLI.getLibcallName(LC) != nullptr;
}
-/// Return true if sincos libcall is available and can be used to combine sin
-/// and cos.
-static bool canCombineSinCosLibcall(SDNode *Node, const TargetLowering &TLI,
- const TargetMachine &TM) {
- if (!isSinCosLibcallAvailable(Node, TLI))
- return false;
- // GNU sin/cos functions set errno while sincos does not. Therefore
- // combining sin and cos is only safe if unsafe-fpmath is enabled.
- if (TM.getTargetTriple().isGNUEnvironment() && !TM.Options.UnsafeFPMath)
- return false;
- return true;
-}
-
/// Only issue sincos libcall if both sin and cos are needed.
static bool useSinCos(SDNode *Node) {
unsigned OtherOpcode = Node->getOpcode() == ISD::FSIN
@@ -3247,7 +3234,7 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
// Turn fsin / fcos into ISD::FSINCOS node if there are a pair of fsin /
// fcos which share the same operand and both are used.
if ((TLI.isOperationLegalOrCustom(ISD::FSINCOS, VT) ||
- canCombineSinCosLibcall(Node, TLI, TM))
+ isSinCosLibcallAvailable(Node, TLI))
&& useSinCos(Node)) {
SDVTList VTs = DAG.getVTList(VT, VT);
Tmp1 = DAG.getNode(ISD::FSINCOS, dl, VTs, Node->getOperand(0));
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 0d5e07ded25c..a3ba52a148ee 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -1828,10 +1828,11 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N,
TLI.isOperationLegalOrCustom(N->getOpcode() == ISD::ADD ?
ISD::UADDO : ISD::USUBO,
TLI.getTypeToExpandTo(*DAG.getContext(), NVT));
+ TargetLoweringBase::BooleanContent BoolType = TLI.getBooleanContents(NVT);
+
if (hasOVF) {
EVT OvfVT = getSetCCResultType(NVT);
SDVTList VTList = DAG.getVTList(NVT, OvfVT);
- TargetLoweringBase::BooleanContent BoolType = TLI.getBooleanContents(NVT);
int RevOpc;
if (N->getOpcode() == ISD::ADD) {
RevOpc = ISD::SUB;
@@ -1864,6 +1865,13 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N,
Hi = DAG.getNode(ISD::ADD, dl, NVT, makeArrayRef(HiOps, 2));
SDValue Cmp1 = DAG.getSetCC(dl, getSetCCResultType(NVT), Lo, LoOps[0],
ISD::SETULT);
+
+ if (BoolType == TargetLoweringBase::ZeroOrOneBooleanContent) {
+ SDValue Carry = DAG.getZExtOrTrunc(Cmp1, dl, NVT);
+ Hi = DAG.getNode(ISD::ADD, dl, NVT, Hi, Carry);
+ return;
+ }
+
SDValue Carry1 = DAG.getSelect(dl, NVT, Cmp1,
DAG.getConstant(1, dl, NVT),
DAG.getConstant(0, dl, NVT));
@@ -1878,9 +1886,14 @@ void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N,
SDValue Cmp =
DAG.getSetCC(dl, getSetCCResultType(LoOps[0].getValueType()),
LoOps[0], LoOps[1], ISD::SETULT);
- SDValue Borrow = DAG.getSelect(dl, NVT, Cmp,
- DAG.getConstant(1, dl, NVT),
- DAG.getConstant(0, dl, NVT));
+
+ SDValue Borrow;
+ if (BoolType == TargetLoweringBase::ZeroOrOneBooleanContent)
+ Borrow = DAG.getZExtOrTrunc(Cmp, dl, NVT);
+ else
+ Borrow = DAG.getSelect(dl, NVT, Cmp, DAG.getConstant(1, dl, NVT),
+ DAG.getConstant(0, dl, NVT));
+
Hi = DAG.getNode(ISD::SUB, dl, NVT, Hi, Borrow);
}
}
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index dff8bd2ad37d..7abdc76cb004 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -7244,6 +7244,24 @@ void SelectionDAG::TransferDbgValues(SDValue From, SDValue To) {
AddDbgValue(I, ToNode, false);
}
+void SelectionDAG::makeEquivalentMemoryOrdering(LoadSDNode *OldLoad,
+ SDValue NewMemOp) {
+ assert(isa<MemSDNode>(NewMemOp.getNode()) && "Expected a memop node");
+ if (!OldLoad->hasAnyUseOfValue(1))
+ return;
+
+ // The new memory operation must have the same position as the old load in
+ // terms of memory dependency. Create a TokenFactor for the old load and new
+ // memory operation and update uses of the old load's output chain to use that
+ // TokenFactor.
+ SDValue OldChain = SDValue(OldLoad, 1);
+ SDValue NewChain = SDValue(NewMemOp.getNode(), 1);
+ SDValue TokenFactor =
+ getNode(ISD::TokenFactor, SDLoc(OldLoad), MVT::Other, OldChain, NewChain);
+ ReplaceAllUsesOfValueWith(OldChain, TokenFactor);
+ UpdateNodeOperands(TokenFactor.getNode(), OldChain, NewChain);
+}
+
//===----------------------------------------------------------------------===//
// SDNode Class
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index d34ac40b9496..f9f431db55be 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -1496,9 +1496,10 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
true /*isfixed*/, 1 /*origidx*/,
0 /*partOffs*/));
// Create SDNode for the swifterror virtual register.
- OutVals.push_back(DAG.getRegister(FuncInfo.getOrCreateSwiftErrorVReg(
- FuncInfo.MBB, FuncInfo.SwiftErrorArg),
- EVT(TLI.getPointerTy(DL))));
+ OutVals.push_back(
+ DAG.getRegister(FuncInfo.getOrCreateSwiftErrorVRegUseAt(
+ &I, FuncInfo.MBB, FuncInfo.SwiftErrorArg).first,
+ EVT(TLI.getPointerTy(DL))));
}
bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
@@ -3581,8 +3582,7 @@ void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
}
void SelectionDAGBuilder::visitStoreToSwiftError(const StoreInst &I) {
- const TargetLowering &TLI = DAG.getTargetLoweringInfo();
- assert(TLI.supportSwiftError() &&
+ assert(DAG.getTargetLoweringInfo().supportSwiftError() &&
"call visitStoreToSwiftError when backend supports swifterror");
SmallVector<EVT, 4> ValueVTs;
@@ -3595,15 +3595,15 @@ void SelectionDAGBuilder::visitStoreToSwiftError(const StoreInst &I) {
SDValue Src = getValue(SrcV);
// Create a virtual register, then update the virtual register.
- auto &DL = DAG.getDataLayout();
- const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(DL));
- unsigned VReg = FuncInfo.MF->getRegInfo().createVirtualRegister(RC);
+ unsigned VReg; bool CreatedVReg;
+ std::tie(VReg, CreatedVReg) = FuncInfo.getOrCreateSwiftErrorVRegDefAt(&I);
// Chain, DL, Reg, N or Chain, DL, Reg, N, Glue
// Chain can be getRoot or getControlRoot.
SDValue CopyNode = DAG.getCopyToReg(getRoot(), getCurSDLoc(), VReg,
SDValue(Src.getNode(), Src.getResNo()));
DAG.setRoot(CopyNode);
- FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, I.getOperand(1), VReg);
+ if (CreatedVReg)
+ FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, I.getOperand(1), VReg);
}
void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) {
@@ -3633,7 +3633,8 @@ void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) {
// Chain, DL, Reg, VT, Glue or Chain, DL, Reg, VT
SDValue L = DAG.getCopyFromReg(
getRoot(), getCurSDLoc(),
- FuncInfo.getOrCreateSwiftErrorVReg(FuncInfo.MBB, SV), ValueVTs[0]);
+ FuncInfo.getOrCreateSwiftErrorVRegUseAt(&I, FuncInfo.MBB, SV).first,
+ ValueVTs[0]);
setValue(&I, L);
}
@@ -4942,11 +4943,12 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
updateDAGForMaybeTailCall(MM);
return nullptr;
}
- case Intrinsic::memcpy_element_atomic: {
- SDValue Dst = getValue(I.getArgOperand(0));
- SDValue Src = getValue(I.getArgOperand(1));
- SDValue NumElements = getValue(I.getArgOperand(2));
- SDValue ElementSize = getValue(I.getArgOperand(3));
+ case Intrinsic::memcpy_element_unordered_atomic: {
+ const ElementUnorderedAtomicMemCpyInst &MI =
+ cast<ElementUnorderedAtomicMemCpyInst>(I);
+ SDValue Dst = getValue(MI.getRawDest());
+ SDValue Src = getValue(MI.getRawSource());
+ SDValue Length = getValue(MI.getLength());
// Emit a library call.
TargetLowering::ArgListTy Args;
@@ -4958,18 +4960,13 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
Entry.Node = Src;
Args.push_back(Entry);
- Entry.Ty = I.getArgOperand(2)->getType();
- Entry.Node = NumElements;
- Args.push_back(Entry);
-
- Entry.Ty = Type::getInt32Ty(*DAG.getContext());
- Entry.Node = ElementSize;
+ Entry.Ty = MI.getLength()->getType();
+ Entry.Node = Length;
Args.push_back(Entry);
- uint64_t ElementSizeConstant =
- cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
+ uint64_t ElementSizeConstant = MI.getElementSizeInBytes();
RTLIB::Libcall LibraryCall =
- RTLIB::getMEMCPY_ELEMENT_ATOMIC(ElementSizeConstant);
+ RTLIB::getMEMCPY_ELEMENT_UNORDERED_ATOMIC(ElementSizeConstant);
if (LibraryCall == RTLIB::UNKNOWN_LIBCALL)
report_fatal_error("Unsupported element size");
@@ -6030,9 +6027,11 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,
SwiftErrorVal = V;
// We find the virtual register for the actual swifterror argument.
// Instead of using the Value, we use the virtual register instead.
- Entry.Node =
- DAG.getRegister(FuncInfo.getOrCreateSwiftErrorVReg(FuncInfo.MBB, V),
- EVT(TLI.getPointerTy(DL)));
+ Entry.Node = DAG.getRegister(FuncInfo
+ .getOrCreateSwiftErrorVRegUseAt(
+ CS.getInstruction(), FuncInfo.MBB, V)
+ .first,
+ EVT(TLI.getPointerTy(DL)));
}
Args.push_back(Entry);
@@ -6073,11 +6072,13 @@ void SelectionDAGBuilder::LowerCallTo(ImmutableCallSite CS, SDValue Callee,
if (SwiftErrorVal && TLI.supportSwiftError()) {
// Get the last element of InVals.
SDValue Src = CLI.InVals.back();
- const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(DL));
- unsigned VReg = FuncInfo.MF->getRegInfo().createVirtualRegister(RC);
+ unsigned VReg; bool CreatedVReg;
+ std::tie(VReg, CreatedVReg) =
+ FuncInfo.getOrCreateSwiftErrorVRegDefAt(CS.getInstruction());
SDValue CopyNode = CLI.DAG.getCopyToReg(Result.second, CLI.DL, VReg, Src);
// We update the virtual register for the actual swifterror argument.
- FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, SwiftErrorVal, VReg);
+ if (CreatedVReg)
+ FuncInfo.setCurrentSwiftErrorVReg(FuncInfo.MBB, SwiftErrorVal, VReg);
DAG.setRoot(CopyNode);
}
}
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index b67f11f85b70..dcccd17bb98e 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -1055,6 +1055,7 @@ static void setupSwiftErrorVals(const Function &Fn, const TargetLowering *TLI,
FuncInfo->SwiftErrorVals.clear();
FuncInfo->SwiftErrorVRegDefMap.clear();
FuncInfo->SwiftErrorVRegUpwardsUse.clear();
+ FuncInfo->SwiftErrorVRegDefUses.clear();
FuncInfo->SwiftErrorArg = nullptr;
// Check if function has a swifterror argument.
@@ -1278,6 +1279,80 @@ static void propagateSwiftErrorVRegs(FunctionLoweringInfo *FuncInfo) {
}
}
+void preassignSwiftErrorRegs(const TargetLowering *TLI,
+ FunctionLoweringInfo *FuncInfo,
+ BasicBlock::const_iterator Begin,
+ BasicBlock::const_iterator End) {
+ if (!TLI->supportSwiftError() || FuncInfo->SwiftErrorVals.empty())
+ return;
+
+ // Iterator over instructions and assign vregs to swifterror defs and uses.
+ for (auto It = Begin; It != End; ++It) {
+ ImmutableCallSite CS(&*It);
+ if (CS) {
+ // A call-site with a swifterror argument is both use and def.
+ const Value *SwiftErrorAddr = nullptr;
+ for (auto &Arg : CS.args()) {
+ if (!Arg->isSwiftError())
+ continue;
+ // Use of swifterror.
+ assert(!SwiftErrorAddr && "Cannot have multiple swifterror arguments");
+ SwiftErrorAddr = &*Arg;
+ assert(SwiftErrorAddr->isSwiftError() &&
+ "Must have a swifterror value argument");
+ unsigned VReg; bool CreatedReg;
+ std::tie(VReg, CreatedReg) = FuncInfo->getOrCreateSwiftErrorVRegUseAt(
+ &*It, FuncInfo->MBB, SwiftErrorAddr);
+ assert(CreatedReg);
+ }
+ if (!SwiftErrorAddr)
+ continue;
+
+ // Def of swifterror.
+ unsigned VReg; bool CreatedReg;
+ std::tie(VReg, CreatedReg) =
+ FuncInfo->getOrCreateSwiftErrorVRegDefAt(&*It);
+ assert(CreatedReg);
+ FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, SwiftErrorAddr, VReg);
+
+ // A load is a use.
+ } else if (const LoadInst *LI = dyn_cast<const LoadInst>(&*It)) {
+ const Value *V = LI->getOperand(0);
+ if (!V->isSwiftError())
+ continue;
+
+ unsigned VReg; bool CreatedReg;
+ std::tie(VReg, CreatedReg) =
+ FuncInfo->getOrCreateSwiftErrorVRegUseAt(LI, FuncInfo->MBB, V);
+ assert(CreatedReg);
+
+ // A store is a def.
+ } else if (const StoreInst *SI = dyn_cast<const StoreInst>(&*It)) {
+ const Value *SwiftErrorAddr = SI->getOperand(1);
+ if (!SwiftErrorAddr->isSwiftError())
+ continue;
+
+ // Def of swifterror.
+ unsigned VReg; bool CreatedReg;
+ std::tie(VReg, CreatedReg) =
+ FuncInfo->getOrCreateSwiftErrorVRegDefAt(&*It);
+ assert(CreatedReg);
+ FuncInfo->setCurrentSwiftErrorVReg(FuncInfo->MBB, SwiftErrorAddr, VReg);
+
+ // A return in a swiferror returning function is a use.
+ } else if (const ReturnInst *R = dyn_cast<const ReturnInst>(&*It)) {
+ const Function *F = R->getParent()->getParent();
+ if(!F->getAttributes().hasAttrSomewhere(Attribute::SwiftError))
+ continue;
+
+ unsigned VReg; bool CreatedReg;
+ std::tie(VReg, CreatedReg) = FuncInfo->getOrCreateSwiftErrorVRegUseAt(
+ R, FuncInfo->MBB, FuncInfo->SwiftErrorArg);
+ assert(CreatedReg);
+ }
+ }
+}
+
void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
FastISelFailed = false;
// Initialize the Fast-ISel state, if needed.
@@ -1384,6 +1459,10 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
FastIS->startNewBlock();
unsigned NumFastIselRemaining = std::distance(Begin, End);
+
+ // Pre-assign swifterror vregs.
+ preassignSwiftErrorRegs(TLI, FuncInfo, Begin, End);
+
// Do FastISel on as many instructions as possible.
for (; BI != Begin; --BI) {
const Instruction *Inst = &*std::prev(BI);
diff --git a/lib/CodeGen/SplitKit.cpp b/lib/CodeGen/SplitKit.cpp
index 3a50aaa69985..008b984dd961 100644
--- a/lib/CodeGen/SplitKit.cpp
+++ b/lib/CodeGen/SplitKit.cpp
@@ -569,8 +569,7 @@ SlotIndex SplitEditor::buildCopy(unsigned FromReg, unsigned ToReg,
// Greedy heuristic: Keep iterating keeping the best covering subreg index
// each time.
- LaneBitmask LanesLeft =
- LaneMask & ~(TRI.getSubRegIndexLaneMask(BestCover));
+ LaneBitmask LanesLeft = LaneMask & ~(TRI.getSubRegIndexLaneMask(BestIdx));
while (LanesLeft.any()) {
unsigned BestIdx = 0;
int BestCover = INT_MIN;
diff --git a/lib/CodeGen/StackColoring.cpp b/lib/CodeGen/StackColoring.cpp
index acb3676fdd71..6bac39c7ee77 100644
--- a/lib/CodeGen/StackColoring.cpp
+++ b/lib/CodeGen/StackColoring.cpp
@@ -86,10 +86,134 @@ STATISTIC(StackSpaceSaved, "Number of bytes saved due to merging slots.");
STATISTIC(StackSlotMerged, "Number of stack slot merged.");
STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region");
+//===----------------------------------------------------------------------===//
+// StackColoring Pass
+//===----------------------------------------------------------------------===//
+//
+// Stack Coloring reduces stack usage by merging stack slots when they
+// can't be used together. For example, consider the following C program:
+//
+// void bar(char *, int);
+// void foo(bool var) {
+// A: {
+// char z[4096];
+// bar(z, 0);
+// }
+//
+// char *p;
+// char x[4096];
+// char y[4096];
+// if (var) {
+// p = x;
+// } else {
+// bar(y, 1);
+// p = y + 1024;
+// }
+// B:
+// bar(p, 2);
+// }
+//
+// Naively-compiled, this program would use 12k of stack space. However, the
+// stack slot corresponding to `z` is always destroyed before either of the
+// stack slots for `x` or `y` are used, and then `x` is only used if `var`
+// is true, while `y` is only used if `var` is false. So in no time are 2
+// of the stack slots used together, and therefore we can merge them,
+// compiling the function using only a single 4k alloca:
+//
+// void foo(bool var) { // equivalent
+// char x[4096];
+// char *p;
+// bar(x, 0);
+// if (var) {
+// p = x;
+// } else {
+// bar(x, 1);
+// p = x + 1024;
+// }
+// bar(p, 2);
+// }
+//
+// This is an important optimization if we want stack space to be under
+// control in large functions, both open-coded ones and ones created by
+// inlining.
//
// Implementation Notes:
// ---------------------
//
+// An important part of the above reasoning is that `z` can't be accessed
+// while the latter 2 calls to `bar` are running. This is justified because
+// `z`'s lifetime is over after we exit from block `A:`, so any further
+// accesses to it would be UB. The way we represent this information
+// in LLVM is by having frontends delimit blocks with `lifetime.start`
+// and `lifetime.end` intrinsics.
+//
+// The effect of these intrinsics seems to be as follows (maybe I should
+// specify this in the reference?):
+//
+// L1) at start, each stack-slot is marked as *out-of-scope*, unless no
+// lifetime intrinsic refers to that stack slot, in which case
+// it is marked as *in-scope*.
+// L2) on a `lifetime.start`, a stack slot is marked as *in-scope* and
+// the stack slot is overwritten with `undef`.
+// L3) on a `lifetime.end`, a stack slot is marked as *out-of-scope*.
+// L4) on function exit, all stack slots are marked as *out-of-scope*.
+// L5) `lifetime.end` is a no-op when called on a slot that is already
+// *out-of-scope*.
+// L6) memory accesses to *out-of-scope* stack slots are UB.
+// L7) when a stack-slot is marked as *out-of-scope*, all pointers to it
+// are invalidated, unless the slot is "degenerate". This is used to
+// justify not marking slots as in-use until the pointer to them is
+// used, but feels a bit hacky in the presence of things like LICM. See
+// the "Degenerate Slots" section for more details.
+//
+// Now, let's ground stack coloring on these rules. We'll define a slot
+// as *in-use* at a (dynamic) point in execution if it either can be
+// written to at that point, or if it has a live and non-undef content
+// at that point.
+//
+// Obviously, slots that are never *in-use* together can be merged, and
+// in our example `foo`, the slots for `x`, `y` and `z` are never
+// in-use together (of course, sometimes slots that *are* in-use together
+// might still be mergable, but we don't care about that here).
+//
+// In this implementation, we successively merge pairs of slots that are
+// not *in-use* together. We could be smarter - for example, we could merge
+// a single large slot with 2 small slots, or we could construct the
+// interference graph and run a "smart" graph coloring algorithm, but with
+// that aside, how do we find out whether a pair of slots might be *in-use*
+// together?
+//
+// From our rules, we see that *out-of-scope* slots are never *in-use*,
+// and from (L7) we see that "non-degenerate" slots remain non-*in-use*
+// until their address is taken. Therefore, we can approximate slot activity
+// using dataflow.
+//
+// A subtle point: naively, we might try to figure out which pairs of
+// stack-slots interfere by propagating `S in-use` through the CFG for every
+// stack-slot `S`, and having `S` and `T` interfere if there is a CFG point in
+// which they are both *in-use*.
+//
+// That is sound, but overly conservative in some cases: in our (artificial)
+// example `foo`, either `x` or `y` might be in use at the label `B:`, but
+// as `x` is only in use if we came in from the `var` edge and `y` only
+// if we came from the `!var` edge, they still can't be in use together.
+// See PR32488 for an important real-life case.
+//
+// If we wanted to find all points of interference precisely, we could
+// propagate `S in-use` and `S&T in-use` predicates through the CFG. That
+// would be precise, but requires propagating `O(n^2)` dataflow facts.
+//
+// However, we aren't interested in the *set* of points of interference
+// between 2 stack slots, only *whether* there *is* such a point. So we
+// can rely on a little trick: for `S` and `T` to be in-use together,
+// one of them needs to become in-use while the other is in-use (or
+// they might both become in use simultaneously). We can check this
+// by also keeping track of the points at which a stack slot might *start*
+// being in-use.
+//
+// Exact first use:
+// ----------------
+//
// Consider the following motivating example:
//
// int foo() {
@@ -158,6 +282,9 @@ STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region");
// lifetime, we can additionally overlap b1 and b5, giving us a 3*1024
// byte stack (better).
//
+// Degenerate Slots:
+// -----------------
+//
// Relying entirely on first-use of stack slots is problematic,
// however, due to the fact that optimizations can sometimes migrate
// uses of a variable outside of its lifetime start/end region. Here
@@ -237,10 +364,6 @@ STATISTIC(EscapedAllocas, "Number of allocas that escaped the lifetime region");
// for "b" then it will appear that 'b' has a degenerate lifetime.
//
-//===----------------------------------------------------------------------===//
-// StackColoring Pass
-//===----------------------------------------------------------------------===//
-
namespace {
/// StackColoring - A machine pass for merging disjoint stack allocations,
/// marked by the LIFETIME_START and LIFETIME_END pseudo instructions.
@@ -271,8 +394,11 @@ class StackColoring : public MachineFunctionPass {
/// Maps basic blocks to a serial number.
SmallVector<const MachineBasicBlock*, 8> BasicBlockNumbering;
- /// Maps liveness intervals for each slot.
+ /// Maps slots to their use interval. Outside of this interval, slots
+ /// values are either dead or `undef` and they will not be written to.
SmallVector<std::unique_ptr<LiveInterval>, 16> Intervals;
+ /// Maps slots to the points where they can become in-use.
+ SmallVector<SmallVector<SlotIndex, 4>, 16> LiveStarts;
/// VNInfo is used for the construction of LiveIntervals.
VNInfo::Allocator VNInfoAllocator;
/// SlotIndex analysis object.
@@ -672,15 +798,22 @@ void StackColoring::calculateLocalLiveness()
void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
SmallVector<SlotIndex, 16> Starts;
- SmallVector<SlotIndex, 16> Finishes;
+ SmallVector<bool, 16> DefinitelyInUse;
// For each block, find which slots are active within this block
// and update the live intervals.
for (const MachineBasicBlock &MBB : *MF) {
Starts.clear();
Starts.resize(NumSlots);
- Finishes.clear();
- Finishes.resize(NumSlots);
+ DefinitelyInUse.clear();
+ DefinitelyInUse.resize(NumSlots);
+
+ // Start the interval of the slots that we previously found to be 'in-use'.
+ BlockLifetimeInfo &MBBLiveness = BlockLiveness[&MBB];
+ for (int pos = MBBLiveness.LiveIn.find_first(); pos != -1;
+ pos = MBBLiveness.LiveIn.find_next(pos)) {
+ Starts[pos] = Indexes->getMBBStartIdx(&MBB);
+ }
// Create the interval for the basic blocks containing lifetime begin/end.
for (const MachineInstr &MI : MBB) {
@@ -692,66 +825,35 @@ void StackColoring::calculateLiveIntervals(unsigned NumSlots) {
SlotIndex ThisIndex = Indexes->getInstructionIndex(MI);
for (auto Slot : slots) {
if (IsStart) {
- if (!Starts[Slot].isValid() || Starts[Slot] > ThisIndex)
+ // If a slot is already definitely in use, we don't have to emit
+ // a new start marker because there is already a pre-existing
+ // one.
+ if (!DefinitelyInUse[Slot]) {
+ LiveStarts[Slot].push_back(ThisIndex);
+ DefinitelyInUse[Slot] = true;
+ }
+ if (!Starts[Slot].isValid())
Starts[Slot] = ThisIndex;
} else {
- if (!Finishes[Slot].isValid() || Finishes[Slot] < ThisIndex)
- Finishes[Slot] = ThisIndex;
+ if (Starts[Slot].isValid()) {
+ VNInfo *VNI = Intervals[Slot]->getValNumInfo(0);
+ Intervals[Slot]->addSegment(
+ LiveInterval::Segment(Starts[Slot], ThisIndex, VNI));
+ Starts[Slot] = SlotIndex(); // Invalidate the start index
+ DefinitelyInUse[Slot] = false;
+ }
}
}
}
- // Create the interval of the blocks that we previously found to be 'alive'.
- BlockLifetimeInfo &MBBLiveness = BlockLiveness[&MBB];
- for (unsigned pos : MBBLiveness.LiveIn.set_bits()) {
- Starts[pos] = Indexes->getMBBStartIdx(&MBB);
- }
- for (unsigned pos : MBBLiveness.LiveOut.set_bits()) {
- Finishes[pos] = Indexes->getMBBEndIdx(&MBB);
- }
-
+ // Finish up started segments
for (unsigned i = 0; i < NumSlots; ++i) {
- //
- // When LifetimeStartOnFirstUse is turned on, data flow analysis
- // is forward (from starts to ends), not bidirectional. A
- // consequence of this is that we can wind up in situations
- // where Starts[i] is invalid but Finishes[i] is valid and vice
- // versa. Example:
- //
- // LIFETIME_START x
- // if (...) {
- // <use of x>
- // throw ...;
- // }
- // LIFETIME_END x
- // return 2;
- //
- //
- // Here the slot for "x" will not be live into the block
- // containing the "return 2" (since lifetimes start with first
- // use, not at the dominating LIFETIME_START marker).
- //
- if (Starts[i].isValid() && !Finishes[i].isValid()) {
- Finishes[i] = Indexes->getMBBEndIdx(&MBB);
- }
if (!Starts[i].isValid())
continue;
- assert(Starts[i] && Finishes[i] && "Invalid interval");
- VNInfo *ValNum = Intervals[i]->getValNumInfo(0);
- SlotIndex S = Starts[i];
- SlotIndex F = Finishes[i];
- if (S < F) {
- // We have a single consecutive region.
- Intervals[i]->addSegment(LiveInterval::Segment(S, F, ValNum));
- } else {
- // We have two non-consecutive regions. This happens when
- // LIFETIME_START appears after the LIFETIME_END marker.
- SlotIndex NewStart = Indexes->getMBBStartIdx(&MBB);
- SlotIndex NewFin = Indexes->getMBBEndIdx(&MBB);
- Intervals[i]->addSegment(LiveInterval::Segment(NewStart, F, ValNum));
- Intervals[i]->addSegment(LiveInterval::Segment(S, NewFin, ValNum));
- }
+ SlotIndex EndIdx = Indexes->getMBBEndIdx(&MBB);
+ VNInfo *VNI = Intervals[i]->getValNumInfo(0);
+ Intervals[i]->addSegment(LiveInterval::Segment(Starts[i], EndIdx, VNI));
}
}
}
@@ -981,6 +1083,7 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
BasicBlockNumbering.clear();
Markers.clear();
Intervals.clear();
+ LiveStarts.clear();
VNInfoAllocator.Reset();
unsigned NumSlots = MFI->getObjectIndexEnd();
@@ -992,6 +1095,7 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
SmallVector<int, 8> SortedSlots;
SortedSlots.reserve(NumSlots);
Intervals.reserve(NumSlots);
+ LiveStarts.resize(NumSlots);
unsigned NumMarkers = collectMarkers(NumSlots);
@@ -1063,6 +1167,9 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
return MFI->getObjectSize(LHS) > MFI->getObjectSize(RHS);
});
+ for (auto &s : LiveStarts)
+ std::sort(s.begin(), s.end());
+
bool Changed = true;
while (Changed) {
Changed = false;
@@ -1078,12 +1185,22 @@ bool StackColoring::runOnMachineFunction(MachineFunction &Func) {
int SecondSlot = SortedSlots[J];
LiveInterval *First = &*Intervals[FirstSlot];
LiveInterval *Second = &*Intervals[SecondSlot];
+ auto &FirstS = LiveStarts[FirstSlot];
+ auto &SecondS = LiveStarts[SecondSlot];
assert (!First->empty() && !Second->empty() && "Found an empty range");
- // Merge disjoint slots.
- if (!First->overlaps(*Second)) {
+ // Merge disjoint slots. This is a little bit tricky - see the
+ // Implementation Notes section for an explanation.
+ if (!First->isLiveAtIndexes(SecondS) &&
+ !Second->isLiveAtIndexes(FirstS)) {
Changed = true;
First->MergeSegmentsInAsValue(*Second, First->getValNumInfo(0));
+
+ int OldSize = FirstS.size();
+ FirstS.append(SecondS.begin(), SecondS.end());
+ auto Mid = FirstS.begin() + OldSize;
+ std::inplace_merge(FirstS.begin(), Mid, FirstS.end());
+
SlotRemap[SecondSlot] = FirstSlot;
SortedSlots[J] = -1;
DEBUG(dbgs()<<"Merging #"<<FirstSlot<<" and slots #"<<
diff --git a/lib/CodeGen/TargetLoweringBase.cpp b/lib/CodeGen/TargetLoweringBase.cpp
index 581cfaf60755..e9d38c10c860 100644
--- a/lib/CodeGen/TargetLoweringBase.cpp
+++ b/lib/CodeGen/TargetLoweringBase.cpp
@@ -374,11 +374,16 @@ static void InitLibcallNames(const char **Names, const Triple &TT) {
Names[RTLIB::MEMCPY] = "memcpy";
Names[RTLIB::MEMMOVE] = "memmove";
Names[RTLIB::MEMSET] = "memset";
- Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_1] = "__llvm_memcpy_element_atomic_1";
- Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_2] = "__llvm_memcpy_element_atomic_2";
- Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_4] = "__llvm_memcpy_element_atomic_4";
- Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_8] = "__llvm_memcpy_element_atomic_8";
- Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_16] = "__llvm_memcpy_element_atomic_16";
+ Names[RTLIB::MEMCPY_ELEMENT_UNORDERED_ATOMIC_1] =
+ "__llvm_memcpy_element_unordered_atomic_1";
+ Names[RTLIB::MEMCPY_ELEMENT_UNORDERED_ATOMIC_2] =
+ "__llvm_memcpy_element_unordered_atomic_2";
+ Names[RTLIB::MEMCPY_ELEMENT_UNORDERED_ATOMIC_4] =
+ "__llvm_memcpy_element_unordered_atomic_4";
+ Names[RTLIB::MEMCPY_ELEMENT_UNORDERED_ATOMIC_8] =
+ "__llvm_memcpy_element_unordered_atomic_8";
+ Names[RTLIB::MEMCPY_ELEMENT_UNORDERED_ATOMIC_16] =
+ "__llvm_memcpy_element_unordered_atomic_16";
Names[RTLIB::UNWIND_RESUME] = "_Unwind_Resume";
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_1] = "__sync_val_compare_and_swap_1";
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_2] = "__sync_val_compare_and_swap_2";
@@ -781,22 +786,21 @@ RTLIB::Libcall RTLIB::getSYNC(unsigned Opc, MVT VT) {
return UNKNOWN_LIBCALL;
}
-RTLIB::Libcall RTLIB::getMEMCPY_ELEMENT_ATOMIC(uint64_t ElementSize) {
+RTLIB::Libcall RTLIB::getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize) {
switch (ElementSize) {
case 1:
- return MEMCPY_ELEMENT_ATOMIC_1;
+ return MEMCPY_ELEMENT_UNORDERED_ATOMIC_1;
case 2:
- return MEMCPY_ELEMENT_ATOMIC_2;
+ return MEMCPY_ELEMENT_UNORDERED_ATOMIC_2;
case 4:
- return MEMCPY_ELEMENT_ATOMIC_4;
+ return MEMCPY_ELEMENT_UNORDERED_ATOMIC_4;
case 8:
- return MEMCPY_ELEMENT_ATOMIC_8;
+ return MEMCPY_ELEMENT_UNORDERED_ATOMIC_8;
case 16:
- return MEMCPY_ELEMENT_ATOMIC_16;
+ return MEMCPY_ELEMENT_UNORDERED_ATOMIC_16;
default:
return UNKNOWN_LIBCALL;
}
-
}
/// InitCmpLibcallCCs - Set default comparison libcall CC.
diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index a0c68e1dcce8..6922e33c8d6c 100644
--- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -61,9 +61,11 @@
using namespace llvm;
using namespace dwarf;
-static void GetObjCImageInfo(ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
- unsigned &Version, unsigned &Flags,
+static void GetObjCImageInfo(Module &M, unsigned &Version, unsigned &Flags,
StringRef &Section) {
+ SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
+ M.getModuleFlagsMetadata(ModuleFlags);
+
for (const auto &MFE: ModuleFlags) {
// Ignore flags with 'Require' behaviour.
if (MFE.Behavior == Module::Require)
@@ -88,14 +90,13 @@ static void GetObjCImageInfo(ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
// ELF
//===----------------------------------------------------------------------===//
-void TargetLoweringObjectFileELF::emitModuleFlags(
- MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
- const TargetMachine &TM) const {
+void TargetLoweringObjectFileELF::emitModuleMetadata(
+ MCStreamer &Streamer, Module &M, const TargetMachine &TM) const {
unsigned Version = 0;
unsigned Flags = 0;
StringRef Section;
- GetObjCImageInfo(ModuleFlags, Version, Flags, Section);
+ GetObjCImageInfo(M, Version, Flags, Section);
if (Section.empty())
return;
@@ -618,20 +619,10 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
}
}
-/// emitModuleFlags - Perform code emission for module flags.
-void TargetLoweringObjectFileMachO::emitModuleFlags(
- MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
- const TargetMachine &TM) const {
- MDNode *LinkerOptions = nullptr;
-
- for (const auto &MFE : ModuleFlags) {
- StringRef Key = MFE.Key->getString();
- if (Key == "Linker Options")
- LinkerOptions = cast<MDNode>(MFE.Val);
- }
-
+void TargetLoweringObjectFileMachO::emitModuleMetadata(
+ MCStreamer &Streamer, Module &M, const TargetMachine &TM) const {
// Emit the linker options if present.
- if (LinkerOptions) {
+ if (auto *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
for (const auto &Option : LinkerOptions->operands()) {
SmallVector<std::string, 4> StrOptions;
for (const auto &Piece : cast<MDNode>(Option)->operands())
@@ -643,7 +634,8 @@ void TargetLoweringObjectFileMachO::emitModuleFlags(
unsigned VersionVal = 0;
unsigned ImageInfoFlags = 0;
StringRef SectionVal;
- GetObjCImageInfo(ModuleFlags, VersionVal, ImageInfoFlags, SectionVal);
+
+ GetObjCImageInfo(M, VersionVal, ImageInfoFlags, SectionVal);
// The section is mandatory. If we don't have it, then we don't have GC info.
if (SectionVal.empty())
@@ -1159,18 +1151,9 @@ MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable(
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID);
}
-void TargetLoweringObjectFileCOFF::emitModuleFlags(
- MCStreamer &Streamer, ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
- const TargetMachine &TM) const {
- MDNode *LinkerOptions = nullptr;
-
- for (const auto &MFE : ModuleFlags) {
- StringRef Key = MFE.Key->getString();
- if (Key == "Linker Options")
- LinkerOptions = cast<MDNode>(MFE.Val);
- }
-
- if (LinkerOptions) {
+void TargetLoweringObjectFileCOFF::emitModuleMetadata(
+ MCStreamer &Streamer, Module &M, const TargetMachine &TM) const {
+ if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
// Emit the linker options to the linker .drectve section. According to the
// spec, this section is a space-separated string containing flags for
// linker.
@@ -1190,7 +1173,7 @@ void TargetLoweringObjectFileCOFF::emitModuleFlags(
unsigned Flags = 0;
StringRef Section;
- GetObjCImageInfo(ModuleFlags, Version, Flags, Section);
+ GetObjCImageInfo(M, Version, Flags, Section);
if (Section.empty())
return;
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt
index 2f9e8981b698..f916695a8439 100644
--- a/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -20,6 +20,7 @@ add_llvm_library(LLVMDebugInfoCodeView
LazyRandomTypeCollection.cpp
Line.cpp
RecordSerialization.cpp
+ StringsAndChecksums.cpp
SymbolRecordMapping.cpp
SymbolDumper.cpp
SymbolSerializer.cpp
@@ -32,7 +33,7 @@ add_llvm_library(LLVMDebugInfoCodeView
TypeSerializer.cpp
TypeStreamMerger.cpp
TypeTableCollection.cpp
-
+
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView
)
diff --git a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
index 6e647c4b976b..de02525270c4 100644
--- a/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
+++ b/lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
@@ -58,6 +58,10 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
uint32_t Begin = Writer.getOffset();
uint32_t End = Begin + StringSize;
+ // Write a null string at the beginning.
+ if (auto EC = Writer.writeCString(StringRef()))
+ return EC;
+
for (auto &Pair : Strings) {
StringRef S = Pair.getKey();
uint32_t Offset = Begin + Pair.getValue();
@@ -68,6 +72,7 @@ Error DebugStringTableSubsection::commit(BinaryStreamWriter &Writer) const {
}
Writer.setOffset(End);
+ assert((End - Begin) == StringSize);
return Error::success();
}
diff --git a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
index e9124e68fe82..334c5e002bbc 100644
--- a/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
+++ b/lib/DebugInfo/CodeView/DebugSubsectionRecord.cpp
@@ -50,7 +50,7 @@ DebugSubsectionKind DebugSubsectionRecord::kind() const { return Kind; }
BinaryStreamRef DebugSubsectionRecord::getRecordData() const { return Data; }
DebugSubsectionRecordBuilder::DebugSubsectionRecordBuilder(
- std::unique_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
+ std::shared_ptr<DebugSubsection> Subsection, CodeViewContainer Container)
: Subsection(std::move(Subsection)), Container(Container) {}
uint32_t DebugSubsectionRecordBuilder::calculateSerializedLength() {
diff --git a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
index 8550107741ce..9b824333369b 100644
--- a/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
+++ b/lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
@@ -26,40 +26,9 @@
using namespace llvm;
using namespace llvm::codeview;
-DebugSubsectionState::DebugSubsectionState() {}
-
-DebugSubsectionState::DebugSubsectionState(
- const DebugStringTableSubsectionRef &Strings)
- : Strings(&Strings) {}
-
-DebugSubsectionState::DebugSubsectionState(
- const DebugStringTableSubsectionRef &Strings,
- const DebugChecksumsSubsectionRef &Checksums)
- : Strings(&Strings), Checksums(&Checksums) {}
-
-void DebugSubsectionState::initializeStrings(const DebugSubsectionRecord &SR) {
- assert(SR.kind() == DebugSubsectionKind::StringTable);
- assert(!Strings && "Found a string table even though we already have one!");
-
- OwnedStrings = llvm::make_unique<DebugStringTableSubsectionRef>();
- consumeError(OwnedStrings->initialize(SR.getRecordData()));
- Strings = OwnedStrings.get();
-}
-
-void DebugSubsectionState::initializeChecksums(
- const DebugSubsectionRecord &FCR) {
- assert(FCR.kind() == DebugSubsectionKind::FileChecksums);
- if (Checksums)
- return;
-
- OwnedChecksums = llvm::make_unique<DebugChecksumsSubsectionRef>();
- consumeError(OwnedChecksums->initialize(FCR.getRecordData()));
- Checksums = OwnedChecksums.get();
-}
-
-Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R,
- DebugSubsectionVisitor &V,
- const DebugSubsectionState &State) {
+Error llvm::codeview::visitDebugSubsection(
+ const DebugSubsectionRecord &R, DebugSubsectionVisitor &V,
+ const StringsAndChecksumsRef &State) {
BinaryStreamReader Reader(R.getRecordData());
switch (R.kind()) {
case DebugSubsectionKind::Lines: {
diff --git a/lib/DebugInfo/CodeView/StringsAndChecksums.cpp b/lib/DebugInfo/CodeView/StringsAndChecksums.cpp
new file mode 100644
index 000000000000..928bf8c94f73
--- /dev/null
+++ b/lib/DebugInfo/CodeView/StringsAndChecksums.cpp
@@ -0,0 +1,55 @@
+//===- StringsAndChecksums.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/StringsAndChecksums.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+StringsAndChecksumsRef::StringsAndChecksumsRef() {}
+
+StringsAndChecksumsRef::StringsAndChecksumsRef(
+ const DebugStringTableSubsectionRef &Strings)
+ : Strings(&Strings) {}
+
+StringsAndChecksumsRef::StringsAndChecksumsRef(
+ const DebugStringTableSubsectionRef &Strings,
+ const DebugChecksumsSubsectionRef &Checksums)
+ : Strings(&Strings), Checksums(&Checksums) {}
+
+void StringsAndChecksumsRef::initializeStrings(
+ const DebugSubsectionRecord &SR) {
+ assert(SR.kind() == DebugSubsectionKind::StringTable);
+ assert(!Strings && "Found a string table even though we already have one!");
+
+ OwnedStrings = llvm::make_unique<DebugStringTableSubsectionRef>();
+ consumeError(OwnedStrings->initialize(SR.getRecordData()));
+ Strings = OwnedStrings.get();
+}
+
+void StringsAndChecksumsRef::setChecksums(
+ const DebugChecksumsSubsectionRef &CS) {
+ OwnedChecksums = llvm::make_unique<DebugChecksumsSubsectionRef>();
+ *OwnedChecksums = CS;
+ Checksums = OwnedChecksums.get();
+}
+
+void StringsAndChecksumsRef::initializeChecksums(
+ const DebugSubsectionRecord &FCR) {
+ assert(FCR.kind() == DebugSubsectionKind::FileChecksums);
+ if (Checksums)
+ return;
+
+ OwnedChecksums = llvm::make_unique<DebugChecksumsSubsectionRef>();
+ consumeError(OwnedChecksums->initialize(FCR.getRecordData()));
+ Checksums = OwnedChecksums.get();
+}
diff --git a/lib/DebugInfo/CodeView/SymbolDumper.cpp b/lib/DebugInfo/CodeView/SymbolDumper.cpp
index 66045933ce9b..36abafc079ed 100644
--- a/lib/DebugInfo/CodeView/SymbolDumper.cpp
+++ b/lib/DebugInfo/CodeView/SymbolDumper.cpp
@@ -212,7 +212,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
FileStaticSym &FileStatic) {
DictScope S(W, "FileStatic");
- W.printNumber("Index", FileStatic.Index);
+ printTypeIndex("Index", FileStatic.Index);
W.printNumber("ModFilenameOffset", FileStatic.ModFilenameOffset);
W.printFlags("Flags", uint16_t(FileStatic.Flags), getLocalFlagNames());
W.printString("Name", FileStatic.Name);
@@ -516,7 +516,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
RegisterSym &Register) {
DictScope S(W, "RegisterSym");
- W.printNumber("Type", Register.Index);
+ printTypeIndex("Type", Register.Index);
W.printEnum("Seg", uint16_t(Register.Register), getRegisterNames());
W.printString("Name", Register.Name);
return Error::success();
@@ -524,7 +524,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
DictScope S(W, "PublicSym");
- W.printNumber("Type", Public.Index);
+ printTypeIndex("Type", Public.Index);
W.printNumber("Seg", Public.Segment);
W.printNumber("Off", Public.Offset);
W.printString("Name", Public.Name);
@@ -631,7 +631,7 @@ Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
W.printHex("Offset", RegRel.Offset);
printTypeIndex("Type", RegRel.Type);
- W.printHex("Register", RegRel.Register);
+ W.printEnum("Register", uint16_t(RegRel.Register), getRegisterNames());
W.printString("VarName", RegRel.Name);
return Error::success();
}
diff --git a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
index ea46841a70f6..d731dc1b0a37 100644
--- a/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
+++ b/lib/DebugInfo/CodeView/SymbolRecordMapping.cpp
@@ -307,7 +307,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
error(IO.mapInteger(FrameCookie.CodeOffset));
error(IO.mapInteger(FrameCookie.Register));
- error(IO.mapInteger(FrameCookie.CookieKind));
+ error(IO.mapEnum(FrameCookie.CookieKind));
error(IO.mapInteger(FrameCookie.Flags));
return Error::success();
@@ -439,7 +439,7 @@ Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
error(IO.mapInteger(RegRel.Offset));
error(IO.mapInteger(RegRel.Type));
- error(IO.mapInteger(RegRel.Register));
+ error(IO.mapEnum(RegRel.Register));
error(IO.mapStringZ(RegRel.Name));
return Error::success();
diff --git a/lib/DebugInfo/CodeView/TypeDatabase.cpp b/lib/DebugInfo/CodeView/TypeDatabase.cpp
index af05d2dc294b..08f848b36a9d 100644
--- a/lib/DebugInfo/CodeView/TypeDatabase.cpp
+++ b/lib/DebugInfo/CodeView/TypeDatabase.cpp
@@ -12,59 +12,6 @@
using namespace llvm;
using namespace llvm::codeview;
-namespace {
-struct SimpleTypeEntry {
- StringRef Name;
- SimpleTypeKind Kind;
-};
-}
-
-/// The names here all end in "*". If the simple type is a pointer type, we
-/// return the whole name. Otherwise we lop off the last character in our
-/// StringRef.
-static const SimpleTypeEntry SimpleTypeNames[] = {
- {"void*", SimpleTypeKind::Void},
- {"<not translated>*", SimpleTypeKind::NotTranslated},
- {"HRESULT*", SimpleTypeKind::HResult},
- {"signed char*", SimpleTypeKind::SignedCharacter},
- {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
- {"char*", SimpleTypeKind::NarrowCharacter},
- {"wchar_t*", SimpleTypeKind::WideCharacter},
- {"char16_t*", SimpleTypeKind::Character16},
- {"char32_t*", SimpleTypeKind::Character32},
- {"__int8*", SimpleTypeKind::SByte},
- {"unsigned __int8*", SimpleTypeKind::Byte},
- {"short*", SimpleTypeKind::Int16Short},
- {"unsigned short*", SimpleTypeKind::UInt16Short},
- {"__int16*", SimpleTypeKind::Int16},
- {"unsigned __int16*", SimpleTypeKind::UInt16},
- {"long*", SimpleTypeKind::Int32Long},
- {"unsigned long*", SimpleTypeKind::UInt32Long},
- {"int*", SimpleTypeKind::Int32},
- {"unsigned*", SimpleTypeKind::UInt32},
- {"__int64*", SimpleTypeKind::Int64Quad},
- {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
- {"__int64*", SimpleTypeKind::Int64},
- {"unsigned __int64*", SimpleTypeKind::UInt64},
- {"__int128*", SimpleTypeKind::Int128},
- {"unsigned __int128*", SimpleTypeKind::UInt128},
- {"__half*", SimpleTypeKind::Float16},
- {"float*", SimpleTypeKind::Float32},
- {"float*", SimpleTypeKind::Float32PartialPrecision},
- {"__float48*", SimpleTypeKind::Float48},
- {"double*", SimpleTypeKind::Float64},
- {"long double*", SimpleTypeKind::Float80},
- {"__float128*", SimpleTypeKind::Float128},
- {"_Complex float*", SimpleTypeKind::Complex32},
- {"_Complex double*", SimpleTypeKind::Complex64},
- {"_Complex long double*", SimpleTypeKind::Complex80},
- {"_Complex __float128*", SimpleTypeKind::Complex128},
- {"bool*", SimpleTypeKind::Boolean8},
- {"__bool16*", SimpleTypeKind::Boolean16},
- {"__bool32*", SimpleTypeKind::Boolean32},
- {"__bool64*", SimpleTypeKind::Boolean64},
-};
-
TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) {
CVUDTNames.resize(Capacity);
TypeRecords.resize(Capacity);
@@ -103,22 +50,8 @@ StringRef TypeDatabase::saveTypeName(StringRef TypeName) {
}
StringRef TypeDatabase::getTypeName(TypeIndex Index) const {
- if (Index.isNoneType())
- return "<no type>";
-
- if (Index.isSimple()) {
- // This is a simple type.
- for (const auto &SimpleTypeName : SimpleTypeNames) {
- if (SimpleTypeName.Kind == Index.getSimpleKind()) {
- if (Index.getSimpleMode() == SimpleTypeMode::Direct)
- return SimpleTypeName.Name.drop_back(1);
- // Otherwise, this is a pointer type. We gloss over the distinction
- // between near, far, 64, 32, etc, and just give a pointer type.
- return SimpleTypeName.Name;
- }
- }
- return "<unknown simple type>";
- }
+ if (Index.isNoneType() || Index.isSimple())
+ return TypeIndex::simpleTypeName(Index);
if (contains(Index))
return CVUDTNames[Index.toArrayIndex()];
diff --git a/lib/DebugInfo/CodeView/TypeIndex.cpp b/lib/DebugInfo/CodeView/TypeIndex.cpp
index 20ba6470cd5b..24fe5fcb28d4 100644
--- a/lib/DebugInfo/CodeView/TypeIndex.cpp
+++ b/lib/DebugInfo/CodeView/TypeIndex.cpp
@@ -15,11 +15,88 @@
using namespace llvm;
using namespace llvm::codeview;
+namespace {
+struct SimpleTypeEntry {
+ StringRef Name;
+ SimpleTypeKind Kind;
+};
+
+/// The names here all end in "*". If the simple type is a pointer type, we
+/// return the whole name. Otherwise we lop off the last character in our
+/// StringRef.
+static const SimpleTypeEntry SimpleTypeNames[] = {
+ {"void*", SimpleTypeKind::Void},
+ {"<not translated>*", SimpleTypeKind::NotTranslated},
+ {"HRESULT*", SimpleTypeKind::HResult},
+ {"signed char*", SimpleTypeKind::SignedCharacter},
+ {"unsigned char*", SimpleTypeKind::UnsignedCharacter},
+ {"char*", SimpleTypeKind::NarrowCharacter},
+ {"wchar_t*", SimpleTypeKind::WideCharacter},
+ {"char16_t*", SimpleTypeKind::Character16},
+ {"char32_t*", SimpleTypeKind::Character32},
+ {"__int8*", SimpleTypeKind::SByte},
+ {"unsigned __int8*", SimpleTypeKind::Byte},
+ {"short*", SimpleTypeKind::Int16Short},
+ {"unsigned short*", SimpleTypeKind::UInt16Short},
+ {"__int16*", SimpleTypeKind::Int16},
+ {"unsigned __int16*", SimpleTypeKind::UInt16},
+ {"long*", SimpleTypeKind::Int32Long},
+ {"unsigned long*", SimpleTypeKind::UInt32Long},
+ {"int*", SimpleTypeKind::Int32},
+ {"unsigned*", SimpleTypeKind::UInt32},
+ {"__int64*", SimpleTypeKind::Int64Quad},
+ {"unsigned __int64*", SimpleTypeKind::UInt64Quad},
+ {"__int64*", SimpleTypeKind::Int64},
+ {"unsigned __int64*", SimpleTypeKind::UInt64},
+ {"__int128*", SimpleTypeKind::Int128},
+ {"unsigned __int128*", SimpleTypeKind::UInt128},
+ {"__half*", SimpleTypeKind::Float16},
+ {"float*", SimpleTypeKind::Float32},
+ {"float*", SimpleTypeKind::Float32PartialPrecision},
+ {"__float48*", SimpleTypeKind::Float48},
+ {"double*", SimpleTypeKind::Float64},
+ {"long double*", SimpleTypeKind::Float80},
+ {"__float128*", SimpleTypeKind::Float128},
+ {"_Complex float*", SimpleTypeKind::Complex32},
+ {"_Complex double*", SimpleTypeKind::Complex64},
+ {"_Complex long double*", SimpleTypeKind::Complex80},
+ {"_Complex __float128*", SimpleTypeKind::Complex128},
+ {"bool*", SimpleTypeKind::Boolean8},
+ {"__bool16*", SimpleTypeKind::Boolean16},
+ {"__bool32*", SimpleTypeKind::Boolean32},
+ {"__bool64*", SimpleTypeKind::Boolean64},
+};
+} // namespace
+
+StringRef TypeIndex::simpleTypeName(TypeIndex TI) {
+ assert(TI.isNoneType() || TI.isSimple());
+
+ if (TI.isNoneType())
+ return "<no type>";
+
+ // This is a simple type.
+ for (const auto &SimpleTypeName : SimpleTypeNames) {
+ if (SimpleTypeName.Kind == TI.getSimpleKind()) {
+ if (TI.getSimpleMode() == SimpleTypeMode::Direct)
+ return SimpleTypeName.Name.drop_back(1);
+ // Otherwise, this is a pointer type. We gloss over the distinction
+ // between near, far, 64, 32, etc, and just give a pointer type.
+ return SimpleTypeName.Name;
+ }
+ }
+ return "<unknown simple type>";
+}
+
void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName,
TypeIndex TI, TypeCollection &Types) {
StringRef TypeName;
- if (!TI.isNoneType())
- TypeName = Types.getTypeName(TI);
+ if (!TI.isNoneType()) {
+ if (TI.isSimple())
+ TypeName = TypeIndex::simpleTypeName(TI);
+ else
+ TypeName = Types.getTypeName(TI);
+ }
+
if (!TypeName.empty())
Printer.printHex(FieldName, TypeName, TI.getIndex());
else
diff --git a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
index 11e2e215303c..8704cea60786 100644
--- a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
+++ b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
@@ -34,7 +34,7 @@ static inline PointerMode getPointerMode(uint32_t Attrs) {
static inline bool isMemberPointer(uint32_t Attrs) {
PointerMode Mode = getPointerMode(Attrs);
return Mode == PointerMode::PointerToDataMember ||
- Mode == PointerMode::PointerToDataMember;
+ Mode == PointerMode::PointerToMemberFunction;
}
static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) {
diff --git a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
index 97b52f0fbdd6..87009bf1b6a1 100644
--- a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
+++ b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -55,6 +55,13 @@ bool DWARFAcceleratorTable::extract() {
return true;
}
+uint32_t DWARFAcceleratorTable::getNumBuckets() { return Hdr.NumBuckets; }
+uint32_t DWARFAcceleratorTable::getNumHashes() { return Hdr.NumHashes; }
+uint32_t DWARFAcceleratorTable::getSizeHdr() { return sizeof(Hdr); }
+uint32_t DWARFAcceleratorTable::getHeaderDataLength() {
+ return Hdr.HeaderDataLength;
+}
+
LLVM_DUMP_METHOD void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
// Dump the header.
OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n'
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index 42ab48808f9a..9bafcde57f0a 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -425,248 +425,6 @@ DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) {
return DWARFDie();
}
-namespace {
-
-class Verifier {
- raw_ostream &OS;
- DWARFContext &DCtx;
-public:
- Verifier(raw_ostream &S, DWARFContext &D) : OS(S), DCtx(D) {}
-
- bool HandleDebugInfo() {
- bool Success = true;
- // A map that tracks all references (converted absolute references) so we
- // can verify each reference points to a valid DIE and not an offset that
- // lies between to valid DIEs.
- std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets;
-
- OS << "Verifying .debug_info...\n";
- for (const auto &CU : DCtx.compile_units()) {
- unsigned NumDies = CU->getNumDIEs();
- for (unsigned I = 0; I < NumDies; ++I) {
- auto Die = CU->getDIEAtIndex(I);
- const auto Tag = Die.getTag();
- if (Tag == DW_TAG_null)
- continue;
- for (auto AttrValue : Die.attributes()) {
- const auto Attr = AttrValue.Attr;
- const auto Form = AttrValue.Value.getForm();
- switch (Attr) {
- case DW_AT_ranges:
- // Make sure the offset in the DW_AT_ranges attribute is valid.
- if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
- if (*SectionOffset >= DCtx.getRangeSection().Data.size()) {
- Success = false;
- OS << "error: DW_AT_ranges offset is beyond .debug_ranges "
- "bounds:\n";
- Die.dump(OS, 0);
- OS << "\n";
- }
- } else {
- Success = false;
- OS << "error: DIE has invalid DW_AT_ranges encoding:\n";
- Die.dump(OS, 0);
- OS << "\n";
- }
- break;
- case DW_AT_stmt_list:
- // Make sure the offset in the DW_AT_stmt_list attribute is valid.
- if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) {
- if (*SectionOffset >= DCtx.getLineSection().Data.size()) {
- Success = false;
- OS << "error: DW_AT_stmt_list offset is beyond .debug_line "
- "bounds: "
- << format("0x%08" PRIx32, *SectionOffset) << "\n";
- CU->getUnitDIE().dump(OS, 0);
- OS << "\n";
- }
- } else {
- Success = false;
- OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n";
- Die.dump(OS, 0);
- OS << "\n";
- }
- break;
-
- default:
- break;
- }
- switch (Form) {
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
- case DW_FORM_ref8:
- case DW_FORM_ref_udata: {
- // Verify all CU relative references are valid CU offsets.
- Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
- assert(RefVal);
- if (RefVal) {
- auto DieCU = Die.getDwarfUnit();
- auto CUSize = DieCU->getNextUnitOffset() - DieCU->getOffset();
- auto CUOffset = AttrValue.Value.getRawUValue();
- if (CUOffset >= CUSize) {
- Success = false;
- OS << "error: " << FormEncodingString(Form) << " CU offset "
- << format("0x%08" PRIx32, CUOffset)
- << " is invalid (must be less than CU size of "
- << format("0x%08" PRIx32, CUSize) << "):\n";
- Die.dump(OS, 0);
- OS << "\n";
- } else {
- // Valid reference, but we will verify it points to an actual
- // DIE later.
- ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
- }
- }
- break;
- }
- case DW_FORM_ref_addr: {
- // Verify all absolute DIE references have valid offsets in the
- // .debug_info section.
- Optional<uint64_t> RefVal = AttrValue.Value.getAsReference();
- assert(RefVal);
- if (RefVal) {
- if(*RefVal >= DCtx.getInfoSection().Data.size()) {
- Success = false;
- OS << "error: DW_FORM_ref_addr offset beyond .debug_info "
- "bounds:\n";
- Die.dump(OS, 0);
- OS << "\n";
- } else {
- // Valid reference, but we will verify it points to an actual
- // DIE later.
- ReferenceToDIEOffsets[*RefVal].insert(Die.getOffset());
- }
- }
- break;
- }
- case DW_FORM_strp: {
- auto SecOffset = AttrValue.Value.getAsSectionOffset();
- assert(SecOffset); // DW_FORM_strp is a section offset.
- if (SecOffset && *SecOffset >= DCtx.getStringSection().size()) {
- Success = false;
- OS << "error: DW_FORM_strp offset beyond .debug_str bounds:\n";
- Die.dump(OS, 0);
- OS << "\n";
- }
- break;
- }
- default:
- break;
- }
- }
- }
- }
-
- // Take all references and make sure they point to an actual DIE by
- // getting the DIE by offset and emitting an error
- OS << "Verifying .debug_info references...\n";
- for (auto Pair: ReferenceToDIEOffsets) {
- auto Die = DCtx.getDIEForOffset(Pair.first);
- if (Die)
- continue;
- Success = false;
- OS << "error: invalid DIE reference " << format("0x%08" PRIx64, Pair.first)
- << ". Offset is in between DIEs:\n";
- for (auto Offset: Pair.second) {
- auto ReferencingDie = DCtx.getDIEForOffset(Offset);
- ReferencingDie.dump(OS, 0);
- OS << "\n";
- }
- OS << "\n";
- }
- return Success;
- }
-
- bool HandleDebugLine() {
- std::map<uint64_t, DWARFDie> StmtListToDie;
- bool Success = true;
- OS << "Verifying .debug_line...\n";
- for (const auto &CU : DCtx.compile_units()) {
- uint32_t LineTableOffset = 0;
- auto CUDie = CU->getUnitDIE();
- auto StmtFormValue = CUDie.find(DW_AT_stmt_list);
- if (!StmtFormValue) {
- // No line table for this compile unit.
- continue;
- }
- // Get the attribute value as a section offset. No need to produce an
- // error here if the encoding isn't correct because we validate this in
- // the .debug_info verifier.
- if (auto StmtSectionOffset = toSectionOffset(StmtFormValue)) {
- LineTableOffset = *StmtSectionOffset;
- if (LineTableOffset >= DCtx.getLineSection().Data.size()) {
- // Make sure we don't get a valid line table back if the offset
- // is wrong.
- assert(DCtx.getLineTableForUnit(CU.get()) == nullptr);
- // Skip this line table as it isn't valid. No need to create an error
- // here because we validate this in the .debug_info verifier.
- continue;
- } else {
- auto Iter = StmtListToDie.find(LineTableOffset);
- if (Iter != StmtListToDie.end()) {
- Success = false;
- OS << "error: two compile unit DIEs, "
- << format("0x%08" PRIx32, Iter->second.getOffset()) << " and "
- << format("0x%08" PRIx32, CUDie.getOffset())
- << ", have the same DW_AT_stmt_list section offset:\n";
- Iter->second.dump(OS, 0);
- CUDie.dump(OS, 0);
- OS << '\n';
- // Already verified this line table before, no need to do it again.
- continue;
- }
- StmtListToDie[LineTableOffset] = CUDie;
- }
- }
- auto LineTable = DCtx.getLineTableForUnit(CU.get());
- if (!LineTable) {
- Success = false;
- OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
- << "] was not able to be parsed for CU:\n";
- CUDie.dump(OS, 0);
- OS << '\n';
- continue;
- }
- uint32_t MaxFileIndex = LineTable->Prologue.FileNames.size();
- uint64_t PrevAddress = 0;
- uint32_t RowIndex = 0;
- for (const auto &Row : LineTable->Rows) {
- if (Row.Address < PrevAddress) {
- Success = false;
- OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
- << "] row[" << RowIndex
- << "] decreases in address from previous row:\n";
-
- DWARFDebugLine::Row::dumpTableHeader(OS);
- if (RowIndex > 0)
- LineTable->Rows[RowIndex - 1].dump(OS);
- Row.dump(OS);
- OS << '\n';
- }
-
- if (Row.File > MaxFileIndex) {
- Success = false;
- OS << "error: .debug_line[" << format("0x%08" PRIx32, LineTableOffset)
- << "][" << RowIndex << "] has invalid file index " << Row.File
- << " (valid values are [1," << MaxFileIndex << "]):\n";
- DWARFDebugLine::Row::dumpTableHeader(OS);
- Row.dump(OS);
- OS << '\n';
- }
- if (Row.EndSequence)
- PrevAddress = 0;
- else
- PrevAddress = Row.Address;
- ++RowIndex;
- }
- }
- return Success;
- }
-};
-
-} // anonymous namespace
-
bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
bool Success = true;
DWARFVerifier verifier(OS, *this);
@@ -678,8 +436,13 @@ bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {
if (!verifier.handleDebugLine())
Success = false;
}
+ if (DumpType == DIDT_All || DumpType == DIDT_AppleNames) {
+ if (!verifier.handleAppleNames())
+ Success = false;
+ }
return Success;
}
+
const DWARFUnitIndex &DWARFContext::getCUIndex() {
if (CUIndex)
return *CUIndex;
@@ -1250,7 +1013,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
continue;
RelSecName = RelSecName.substr(
- RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
+ RelSecName.find_first_not_of("._z")); // Skip . and _ prefixes.
// TODO: Add support for relocations in other sections as needed.
// Record relocations for the debug_info and debug_line sections.
diff --git a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index e6e007896cc8..cf9fec2b3254 100644
--- a/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -514,6 +514,20 @@ static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
}
}
+// This is a workaround for old compilers which do not allow
+// noreturn attribute usage in lambdas. Once the support for those
+// compilers are phased out, we can remove this and return back to
+// a ReportError lambda: [StartOffset](const char *ErrorMsg).
+#define ReportError(ErrorMsg) ReportErrorImpl(StartOffset,ErrorMsg)
+static void LLVM_ATTRIBUTE_NORETURN
+ReportErrorImpl(uint32_t StartOffset, const char *ErrorMsg) {
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS << format(ErrorMsg, StartOffset);
+ OS.flush();
+ report_fatal_error(Str);
+}
+
void DWARFDebugFrame::parse(DataExtractor Data) {
uint32_t Offset = 0;
DenseMap<uint32_t, CIE *> CIEs;
@@ -521,14 +535,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
while (Data.isValidOffset(Offset)) {
uint32_t StartOffset = Offset;
- auto ReportError = [StartOffset](const char *ErrorMsg) {
- std::string Str;
- raw_string_ostream OS(Str);
- OS << format(ErrorMsg, StartOffset);
- OS.flush();
- report_fatal_error(Str);
- };
-
bool IsDWARF64 = false;
uint64_t Length = Data.getU32(&Offset);
uint64_t Id;
@@ -585,7 +591,6 @@ void DWARFDebugFrame::parse(DataExtractor Data) {
switch (AugmentationString[i]) {
default:
ReportError("Unknown augmentation character in entry at %lx");
- llvm_unreachable("ReportError should not return.");
case 'L':
LSDAPointerEncoding = Data.getU8(&Offset);
break;
diff --git a/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 8a544296f65c..a6240fb60143 100644
--- a/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
#include <set>
@@ -275,3 +276,36 @@ bool DWARFVerifier::handleDebugLine() {
verifyDebugLineRows();
return NumDebugLineErrors == 0;
}
+
+bool DWARFVerifier::handleAppleNames() {
+ NumAppleNamesErrors = 0;
+ OS << "Verifying .apple_names...\n";
+
+ DataExtractor AppleNamesSection(DCtx.getAppleNamesSection().Data,
+ DCtx.isLittleEndian(), 0);
+ DataExtractor StrData(DCtx.getStringSection(), DCtx.isLittleEndian(), 0);
+ DWARFAcceleratorTable AppleNames(AppleNamesSection, StrData,
+ DCtx.getAppleNamesSection().Relocs);
+
+ if (!AppleNames.extract()) {
+ OS << "error: cannot extract .apple_names accelerator table\n";
+ return false;
+ }
+
+ // Verify that all buckets have a valid hash index or are empty
+ uint32_t NumBuckets = AppleNames.getNumBuckets();
+ uint32_t NumHashes = AppleNames.getNumHashes();
+
+ uint32_t BucketsOffset =
+ AppleNames.getSizeHdr() + AppleNames.getHeaderDataLength();
+
+ for (uint32_t BucketIdx = 0; BucketIdx < NumBuckets; ++BucketIdx) {
+ uint32_t HashIdx = AppleNamesSection.getU32(&BucketsOffset);
+ if (HashIdx >= NumHashes && HashIdx != UINT32_MAX) {
+ OS << format("error: Bucket[%d] has invalid hash index: [%d]\n",
+ BucketIdx, HashIdx);
+ ++NumAppleNamesErrors;
+ }
+ }
+ return NumAppleNamesErrors == 0;
+}
diff --git a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
index 396dffaa68b1..81a9d3eeec61 100644
--- a/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.cpp
@@ -177,7 +177,7 @@ Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter,
}
void DbiModuleDescriptorBuilder::addDebugSubsection(
- std::unique_ptr<DebugSubsection> Subsection) {
+ std::shared_ptr<DebugSubsection> Subsection) {
assert(Subsection);
C13Builders.push_back(llvm::make_unique<DebugSubsectionRecordBuilder>(
std::move(Subsection), CodeViewContainer::Pdb));
diff --git a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
index 355c7b57f4d1..e7304b444f23 100644
--- a/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp
@@ -45,10 +45,6 @@ void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
-void DbiStreamBuilder::setSectionContribs(ArrayRef<SectionContrib> Arr) {
- SectionContribs = Arr;
-}
-
void DbiStreamBuilder::setSectionMap(ArrayRef<SecMapEntry> SecMap) {
SectionMap = SecMap;
}
@@ -293,23 +289,17 @@ static uint16_t toSecMapFlags(uint32_t Flags) {
return Ret;
}
-// A utility function to create Section Contributions
-// for a given input sections.
-std::vector<SectionContrib> DbiStreamBuilder::createSectionContribs(
- ArrayRef<object::coff_section> SecHdrs) {
- std::vector<SectionContrib> Ret;
-
- // Create a SectionContrib for each input section.
- for (auto &Sec : SecHdrs) {
- Ret.emplace_back();
- auto &Entry = Ret.back();
- memset(&Entry, 0, sizeof(Entry));
-
- Entry.Off = Sec.PointerToRawData;
- Entry.Size = Sec.SizeOfRawData;
- Entry.Characteristics = Sec.Characteristics;
- }
- return Ret;
+void DbiStreamBuilder::addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
+ const object::coff_section *SecHdr) {
+ SectionContrib SC;
+ memset(&SC, 0, sizeof(SC));
+ SC.ISect = (uint16_t)~0U; // This represents nil.
+ SC.Off = SecHdr->PointerToRawData;
+ SC.Size = SecHdr->SizeOfRawData;
+ SC.Characteristics = SecHdr->Characteristics;
+ // Use the module index in the module dbi stream or nil (-1).
+ SC.Imod = ModuleDbi ? ModuleDbi->getModuleIndex() : (uint16_t)~0U;
+ SectionContribs.emplace_back(SC);
}
// A utility function to create a Section Map for a given list of COFF sections.
@@ -372,7 +362,7 @@ Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
if (!SectionContribs.empty()) {
if (auto EC = Writer.writeEnum(DbiSecContribVer60))
return EC;
- if (auto EC = Writer.writeArray(SectionContribs))
+ if (auto EC = Writer.writeArray(makeArrayRef(SectionContribs)))
return EC;
}
diff --git a/lib/DebugInfo/PDB/Native/InfoStream.cpp b/lib/DebugInfo/PDB/Native/InfoStream.cpp
index 7c6069652da6..a3979d480bf4 100644
--- a/lib/DebugInfo/PDB/Native/InfoStream.cpp
+++ b/lib/DebugInfo/PDB/Native/InfoStream.cpp
@@ -102,6 +102,10 @@ InfoStream::named_streams() const {
return NamedStreams.entries();
}
+bool InfoStream::containsIdStream() const {
+ return !!(Features & PdbFeatureContainsIdStream);
+}
+
PdbRaw_ImplVer InfoStream::getVersion() const {
return static_cast<PdbRaw_ImplVer>(Version);
}
diff --git a/lib/DebugInfo/PDB/Native/PDBFile.cpp b/lib/DebugInfo/PDB/Native/PDBFile.cpp
index 1254e23c73eb..a9597cdf4c4d 100644
--- a/lib/DebugInfo/PDB/Native/PDBFile.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -363,6 +363,16 @@ Expected<PDBStringTable &> PDBFile::getStringTable() {
return *Strings;
}
+uint32_t PDBFile::getPointerSize() {
+ auto DbiS = getPDBDbiStream();
+ if (!DbiS)
+ return 0;
+ PDB_Machine Machine = DbiS->getMachineType();
+ if (Machine == PDB_Machine::Amd64)
+ return 8;
+ return 4;
+}
+
bool PDBFile::hasPDBDbiStream() const { return StreamDBI < getNumStreams(); }
bool PDBFile::hasPDBGlobalsStream() {
diff --git a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
index 2c6465e6fb2a..12b0c3b36c1d 100644
--- a/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
@@ -80,6 +80,16 @@ Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) {
}
Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
+
+ if (Ipi && Ipi->getRecordCount() > 0) {
+ // In theory newer PDBs always have an ID stream, but by saying that we're
+ // only going to *really* have an ID stream if there is at least one ID
+ // record, we leave open the opportunity to test older PDBs such as those
+ // that don't have an ID stream.
+ auto &Info = getInfoBuilder();
+ Info.addFeature(PdbRaw_FeatureSig::VC140);
+ }
+
uint32_t StringsLen = Strings.calculateSerializedSize();
if (auto EC = addNamedStream("/names", StringsLen))
diff --git a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
index 6013c342cf02..f9f8ac219d35 100644
--- a/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBStringTable.cpp
@@ -56,7 +56,8 @@ Error PDBStringTable::readStrings(BinaryStreamReader &Reader) {
return Error::success();
}
-codeview::DebugStringTableSubsectionRef PDBStringTable::getStringTable() const {
+const codeview::DebugStringTableSubsectionRef &
+PDBStringTable::getStringTable() const {
return Strings;
}
diff --git a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
index a472181a4895..90acfadd311f 100644
--- a/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
+++ b/lib/DebugInfo/PDB/Native/PDBStringTableBuilder.cpp
@@ -52,6 +52,11 @@ uint32_t PDBStringTableBuilder::calculateSerializedSize() const {
return Size;
}
+void PDBStringTableBuilder::setStrings(
+ const codeview::DebugStringTableSubsection &Strings) {
+ this->Strings = Strings;
+}
+
Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const {
// Write a header
PDBStringTableHeader H;
diff --git a/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/lib/DebugInfo/PDB/Native/PublicsStream.cpp
index 091ac67035dc..8f3474b9ce19 100644
--- a/lib/DebugInfo/PDB/Native/PublicsStream.cpp
+++ b/lib/DebugInfo/PDB/Native/PublicsStream.cpp
@@ -130,4 +130,13 @@ PublicsStream::getSymbols(bool *HadError) const {
return SS.getSymbols(HadError);
}
+Expected<const codeview::CVSymbolArray &>
+PublicsStream::getSymbolArray() const {
+ auto SymbolS = Pdb.getPDBSymbolStream();
+ if (!SymbolS)
+ return SymbolS.takeError();
+
+ return SymbolS->getSymbolArray();
+}
+
Error PublicsStream::commit() { return Error::success(); }
diff --git a/lib/DebugInfo/PDB/Native/TpiHashing.cpp b/lib/DebugInfo/PDB/Native/TpiHashing.cpp
index 16904a5a27ed..91b8d648fcf9 100644
--- a/lib/DebugInfo/PDB/Native/TpiHashing.cpp
+++ b/lib/DebugInfo/PDB/Native/TpiHashing.cpp
@@ -9,6 +9,7 @@
#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/PDB/Native/Hash.h"
#include "llvm/DebugInfo/PDB/Native/RawError.h"
diff --git a/lib/DebugInfo/PDB/UDTLayout.cpp b/lib/DebugInfo/PDB/UDTLayout.cpp
index aacefae80c3a..da353cb6977c 100644
--- a/lib/DebugInfo/PDB/UDTLayout.cpp
+++ b/lib/DebugInfo/PDB/UDTLayout.cpp
@@ -181,13 +181,14 @@ void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
if (Data->getDataKind() == PDB_DataKind::Member)
Members.push_back(std::move(Data));
else
- Other.push_back(std::move(Child));
+ Other.push_back(std::move(Data));
} else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
VTables.push_back(std::move(VT));
else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
Funcs.push_back(std::move(Func));
- else
+ else {
Other.push_back(std::move(Child));
+ }
}
// We don't want to have any re-allocations in the list of bases, so make
diff --git a/lib/Fuzzer/FuzzerDriver.cpp b/lib/Fuzzer/FuzzerDriver.cpp
index 9aad3771784d..0453a7f443b5 100644
--- a/lib/Fuzzer/FuzzerDriver.cpp
+++ b/lib/Fuzzer/FuzzerDriver.cpp
@@ -553,12 +553,12 @@ int FuzzerDriver(int *argc, char ***argv, UserCallback Callback) {
return RunInMultipleProcesses(Args, Flags.workers, Flags.jobs);
const size_t kMaxSaneLen = 1 << 20;
- const size_t kMinDefaultLen = 64;
+ const size_t kMinDefaultLen = 4096;
FuzzingOptions Options;
Options.Verbosity = Flags.verbosity;
Options.MaxLen = Flags.max_len;
Options.ExperimentalLenControl = Flags.experimental_len_control;
- if (Flags.experimental_len_control && Flags.max_len == 64)
+ if (Flags.experimental_len_control && Flags.max_len == kMinDefaultLen)
Options.MaxLen = 1 << 20;
Options.UnitTimeoutSec = Flags.timeout;
Options.ErrorExitCode = Flags.error_exitcode;
diff --git a/lib/Fuzzer/FuzzerLoop.cpp b/lib/Fuzzer/FuzzerLoop.cpp
index f6083282ab61..fbf18357ede6 100644
--- a/lib/Fuzzer/FuzzerLoop.cpp
+++ b/lib/Fuzzer/FuzzerLoop.cpp
@@ -301,7 +301,9 @@ void Fuzzer::SetMaxInputLen(size_t MaxInputLen) {
this->MaxInputLen = MaxInputLen;
this->MaxMutationLen = MaxInputLen;
AllocateCurrentUnitData();
- Printf("INFO: -max_len is not provided, using %zd\n", MaxInputLen);
+ Printf("INFO: -max_len is not provided; "
+ "libFuzzer will not generate inputs larger than %zd bytes\n",
+ MaxInputLen);
}
void Fuzzer::SetMaxMutationLen(size_t MaxMutationLen) {
diff --git a/lib/Fuzzer/FuzzerTracePC.cpp b/lib/Fuzzer/FuzzerTracePC.cpp
index ea93468ea0ed..6f5c7be41062 100644
--- a/lib/Fuzzer/FuzzerTracePC.cpp
+++ b/lib/Fuzzer/FuzzerTracePC.cpp
@@ -53,6 +53,17 @@ size_t TracePC::GetTotalPCCoverage() {
return Res;
}
+
+void TracePC::HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop) {
+ if (Start == Stop) return;
+ if (NumModulesWithInline8bitCounters &&
+ ModuleCounters[NumModulesWithInline8bitCounters-1].Start == Start) return;
+ assert(NumModulesWithInline8bitCounters <
+ sizeof(ModuleCounters) / sizeof(ModuleCounters[0]));
+ ModuleCounters[NumModulesWithInline8bitCounters++] = {Start, Stop};
+ NumInline8bitCounters += Stop - Start;
+}
+
void TracePC::HandleInit(uint32_t *Start, uint32_t *Stop) {
if (Start == Stop || *Start) return;
assert(NumModules < sizeof(Modules) / sizeof(Modules[0]));
@@ -76,6 +87,13 @@ void TracePC::PrintModuleInfo() {
for (size_t i = 0; i < NumModules; i++)
Printf("[%p, %p), ", Modules[i].Start, Modules[i].Stop);
Printf("\n");
+ if (NumModulesWithInline8bitCounters) {
+ Printf("INFO: Loaded %zd modules with %zd inline 8-bit counters\n",
+ NumModulesWithInline8bitCounters, NumInline8bitCounters);
+ for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++)
+ Printf("[%p, %p), ", ModuleCounters[i].Start, ModuleCounters[i].Stop);
+ Printf("\n");
+ }
}
ATTRIBUTE_NO_SANITIZE_ALL
@@ -304,6 +322,11 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *Start, uint32_t *Stop) {
}
ATTRIBUTE_INTERFACE
+void __sanitizer_cov_8bit_counters_init(uint8_t *Start, uint8_t *Stop) {
+ fuzzer::TPC.HandleInline8bitCountersInit(Start, Stop);
+}
+
+ATTRIBUTE_INTERFACE
ATTRIBUTE_NO_SANITIZE_ALL
void __sanitizer_cov_trace_pc_indir(uintptr_t Callee) {
uintptr_t PC = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
diff --git a/lib/Fuzzer/FuzzerTracePC.h b/lib/Fuzzer/FuzzerTracePC.h
index 6523fa06005c..5ec8c590b4df 100644
--- a/lib/Fuzzer/FuzzerTracePC.h
+++ b/lib/Fuzzer/FuzzerTracePC.h
@@ -51,7 +51,8 @@ class TracePC {
// How many bits of PC are used from __sanitizer_cov_trace_pc.
static const size_t kTracePcBits = 18;
- void HandleInit(uint32_t *start, uint32_t *stop);
+ void HandleInit(uint32_t *Start, uint32_t *Stop);
+ void HandleInline8bitCountersInit(uint8_t *Start, uint8_t *Stop);
void HandleCallerCallee(uintptr_t Caller, uintptr_t Callee);
template <class T> void HandleCmp(uintptr_t PC, T Arg1, T Arg2);
size_t GetTotalPCCoverage();
@@ -104,6 +105,10 @@ private:
size_t NumModules; // linker-initialized.
size_t NumGuards; // linker-initialized.
+ struct { uint8_t *Start, *Stop; } ModuleCounters[4096];
+ size_t NumModulesWithInline8bitCounters; // linker-initialized.
+ size_t NumInline8bitCounters;
+
uint8_t *Counters() const;
uintptr_t *PCs() const;
@@ -118,12 +123,24 @@ void ForEachNonZeroByte(const uint8_t *Begin, const uint8_t *End,
size_t FirstFeature, Callback Handle8bitCounter) {
typedef uintptr_t LargeType;
const size_t Step = sizeof(LargeType) / sizeof(uint8_t);
- assert(!(reinterpret_cast<uintptr_t>(Begin) % 64));
- for (auto P = Begin; P < End; P += Step)
+ const size_t StepMask = Step - 1;
+ auto P = Begin;
+ // Iterate by 1 byte until either the alignment boundary or the end.
+ for (; reinterpret_cast<uintptr_t>(P) & StepMask && P < End; P++)
+ if (uint8_t V = *P)
+ Handle8bitCounter(FirstFeature + P - Begin, V);
+
+ // Iterate by Step bytes at a time.
+ for (; P < End; P += Step)
if (LargeType Bundle = *reinterpret_cast<const LargeType *>(P))
for (size_t I = 0; I < Step; I++, Bundle >>= 8)
if (uint8_t V = Bundle & 0xff)
Handle8bitCounter(FirstFeature + P - Begin + I, V);
+
+ // Iterate by 1 byte until the end.
+ for (; P < End; P++)
+ if (uint8_t V = *P)
+ Handle8bitCounter(FirstFeature + P - Begin, V);
}
template <class Callback> // bool Callback(size_t Feature)
@@ -145,8 +162,16 @@ void TracePC::CollectFeatures(Callback HandleFeature) const {
HandleFeature(Idx * 8 + Bit);
};
- ForEachNonZeroByte(Counters, Counters + N, 0, Handle8bitCounter);
- ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), N * 8,
+ size_t FirstFeature = 0;
+ ForEachNonZeroByte(Counters, Counters + N, FirstFeature, Handle8bitCounter);
+ FirstFeature += N * 8;
+ for (size_t i = 0; i < NumModulesWithInline8bitCounters; i++) {
+ ForEachNonZeroByte(ModuleCounters[i].Start, ModuleCounters[i].Stop,
+ FirstFeature, Handle8bitCounter);
+ FirstFeature += 8 * (ModuleCounters[i].Stop - ModuleCounters[i].Start);
+ }
+
+ ForEachNonZeroByte(ExtraCountersBegin(), ExtraCountersEnd(), FirstFeature,
Handle8bitCounter);
if (UseValueProfile)
diff --git a/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp b/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp
index dfb6007b7970..b5a61ddca715 100644
--- a/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp
+++ b/lib/Fuzzer/test/AbsNegAndConstant64Test.cpp
@@ -9,7 +9,7 @@
#include <cstring>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
- if (Size < 16) return 0;
+ if (Size < 16 || Size > 64) return 0;
int64_t x;
uint64_t y;
memcpy(&x, Data, sizeof(x));
diff --git a/lib/Fuzzer/test/CMakeLists.txt b/lib/Fuzzer/test/CMakeLists.txt
index b39938a705f6..1cf6c9502a2b 100644
--- a/lib/Fuzzer/test/CMakeLists.txt
+++ b/lib/Fuzzer/test/CMakeLists.txt
@@ -206,6 +206,9 @@ include_directories(..)
add_subdirectory(no-coverage)
add_subdirectory(trace-pc)
add_subdirectory(ubsan)
+if (NOT MSVC)
+ add_subdirectory(inline-8bit-counters)
+endif()
add_library(LLVMFuzzer-DSO1 SHARED DSO1.cpp)
add_library(LLVMFuzzer-DSO2 SHARED DSO2.cpp)
diff --git a/lib/Fuzzer/test/FourIndependentBranchesTest.cpp b/lib/Fuzzer/test/FourIndependentBranchesTest.cpp
index bbf5ea235c7a..ba963d9b1de8 100644
--- a/lib/Fuzzer/test/FourIndependentBranchesTest.cpp
+++ b/lib/Fuzzer/test/FourIndependentBranchesTest.cpp
@@ -8,6 +8,7 @@
#include <iostream>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 64) return 0;
int bits = 0;
if (Size > 0 && Data[0] == 'F') bits |= 1;
if (Size > 1 && Data[1] == 'U') bits |= 2;
diff --git a/lib/Fuzzer/test/FuzzerUnittest.cpp b/lib/Fuzzer/test/FuzzerUnittest.cpp
index c8beb4331bfa..812894fd947f 100644
--- a/lib/Fuzzer/test/FuzzerUnittest.cpp
+++ b/lib/Fuzzer/test/FuzzerUnittest.cpp
@@ -772,4 +772,16 @@ TEST(Fuzzer, ForEachNonZeroByte) {
Expected = {{108, 1}, {109, 2}, {118, 3}, {120, 4},
{135, 5}, {137, 6}, {146, 7}, {163, 8}};
EXPECT_EQ(Res, Expected);
+
+ Res.clear();
+ ForEachNonZeroByte(Ar + 9, Ar + N, 109, CB);
+ Expected = { {109, 2}, {118, 3}, {120, 4},
+ {135, 5}, {137, 6}, {146, 7}, {163, 8}};
+ EXPECT_EQ(Res, Expected);
+
+ Res.clear();
+ ForEachNonZeroByte(Ar + 9, Ar + N - 9, 109, CB);
+ Expected = { {109, 2}, {118, 3}, {120, 4},
+ {135, 5}, {137, 6}, {146, 7}};
+ EXPECT_EQ(Res, Expected);
}
diff --git a/lib/Fuzzer/test/ShrinkControlFlowTest.cpp b/lib/Fuzzer/test/ShrinkControlFlowTest.cpp
index d09542963626..37eeede7cbff 100644
--- a/lib/Fuzzer/test/ShrinkControlFlowTest.cpp
+++ b/lib/Fuzzer/test/ShrinkControlFlowTest.cpp
@@ -11,6 +11,7 @@
static volatile int Sink;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 64) return 0;
int8_t Ids[256];
memset(Ids, -1, sizeof(Ids));
for (size_t i = 0; i < Size; i++)
diff --git a/lib/Fuzzer/test/SimpleHashTest.cpp b/lib/Fuzzer/test/SimpleHashTest.cpp
index 99e96cb25dcd..a3f4211ebeef 100644
--- a/lib/Fuzzer/test/SimpleHashTest.cpp
+++ b/lib/Fuzzer/test/SimpleHashTest.cpp
@@ -26,7 +26,7 @@ static uint32_t simple_hash(const uint8_t *Data, size_t Size) {
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
- if (Size < 14)
+ if (Size < 14 || Size > 64)
return 0;
uint32_t Hash = simple_hash(&Data[0], Size - 4);
diff --git a/lib/Fuzzer/test/SingleStrncmpTest.cpp b/lib/Fuzzer/test/SingleStrncmpTest.cpp
index b302670fb743..b38c7995d8ff 100644
--- a/lib/Fuzzer/test/SingleStrncmpTest.cpp
+++ b/lib/Fuzzer/test/SingleStrncmpTest.cpp
@@ -8,6 +8,7 @@
#include <cstring>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ if (Size > 64) return 0;
char *S = (char*)Data;
volatile auto Strncmp = &(strncmp); // Make sure strncmp is not inlined.
if (Size >= 6 && !Strncmp(S, "qwerty", 6)) {
diff --git a/lib/Fuzzer/test/TableLookupTest.cpp b/lib/Fuzzer/test/TableLookupTest.cpp
index 8126eeabaf42..4d8ab0611cde 100644
--- a/lib/Fuzzer/test/TableLookupTest.cpp
+++ b/lib/Fuzzer/test/TableLookupTest.cpp
@@ -15,7 +15,6 @@ const size_t N = 1 << 12;
// Define an array of counters that will be understood by libFuzzer
// as extra coverage signal. The array must be:
// * uint8_t
-// * aligned by 64
// * in the section named __libfuzzer_extra_counters.
// The target code may declare more than one such array.
//
@@ -23,7 +22,7 @@ const size_t N = 1 << 12;
// depending on whether multiple occurrences of the event 'Idx'
// is important to distinguish from one occurrence.
#ifdef __linux__
-alignas(64) __attribute__((section("__libfuzzer_extra_counters")))
+__attribute__((section("__libfuzzer_extra_counters")))
#endif
static uint8_t Counters[N];
diff --git a/lib/Fuzzer/test/fuzzer-dirs.test b/lib/Fuzzer/test/fuzzer-dirs.test
index 3de64f278f5d..622ff5da3a29 100644
--- a/lib/Fuzzer/test/fuzzer-dirs.test
+++ b/lib/Fuzzer/test/fuzzer-dirs.test
@@ -5,9 +5,13 @@ RUN: echo b > %t/SUB1/SUB2/b
RUN: echo c > %t/SUB1/SUB2/SUB3/c
RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=SUBDIRS
SUBDIRS: READ units: 3
-RUN: echo -n zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/long
+RUN: echo -n zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz > %t/SUB1/f64
+RUN: cat %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 %t/SUB1/f64 > %t/SUB1/f256
+RUN: cat %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 %t/SUB1/f256 > %t/SUB1/f1024
+RUN: cat %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 %t/SUB1/f1024 > %t/SUB1/f4096
+RUN: cat %t/SUB1/f4096 %t/SUB1/f4096 > %t/SUB1/f8192
RUN: LLVMFuzzer-SimpleTest %t/SUB1 -runs=0 2>&1 | FileCheck %s --check-prefix=LONG
-LONG: INFO: -max_len is not provided, using 93
+LONG: INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 8192 bytes
RUN: rm -rf %t/SUB1
RUN: not LLVMFuzzer-SimpleTest NONEXISTENT_DIR 2>&1 | FileCheck %s --check-prefix=NONEXISTENT_DIR
diff --git a/lib/Fuzzer/test/inline-8bit-counters.test b/lib/Fuzzer/test/inline-8bit-counters.test
new file mode 100644
index 000000000000..8747af81451f
--- /dev/null
+++ b/lib/Fuzzer/test/inline-8bit-counters.test
@@ -0,0 +1,4 @@
+REQUIRES: linux
+CHECK: INFO: Loaded 1 modules with {{.*}} inline 8-bit counters
+CHECK: BINGO
+RUN: LLVMFuzzer-SimpleTest-Inline8bitCounters -runs=1000000 -seed=1 2>&1 | FileCheck %s
diff --git a/lib/Fuzzer/test/inline-8bit-counters/CMakeLists.txt b/lib/Fuzzer/test/inline-8bit-counters/CMakeLists.txt
new file mode 100644
index 000000000000..088ab04fe6a0
--- /dev/null
+++ b/lib/Fuzzer/test/inline-8bit-counters/CMakeLists.txt
@@ -0,0 +1,12 @@
+# These tests are instrumented with -fsanitize-coverage=inline-8bit-counters
+
+set(CMAKE_CXX_FLAGS
+ "${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=trace-pc-guard -fsanitize-coverage=inline-8bit-counters")
+
+set(Inline8bitCounterTests
+ SimpleTest
+ )
+
+foreach(Test ${Inline8bitCounterTests})
+ add_libfuzzer_test(${Test}-Inline8bitCounters SOURCES ../${Test}.cpp)
+endforeach()
diff --git a/lib/Fuzzer/test/trace-pc/CMakeLists.txt b/lib/Fuzzer/test/trace-pc/CMakeLists.txt
index e800f82cc5dc..572fcc983654 100644
--- a/lib/Fuzzer/test/trace-pc/CMakeLists.txt
+++ b/lib/Fuzzer/test/trace-pc/CMakeLists.txt
@@ -1,5 +1,4 @@
-# These tests are not instrumented with coverage and don't
-# have coverage rt in the binary.
+# These tests are instrumented with -fsanitize-coverage=trace-pc
set(CMAKE_CXX_FLAGS
"${LIBFUZZER_FLAGS_BASE} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters,trace-pc-guard -fsanitize-coverage=trace-pc")
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index a20f3f811c8d..3469026ad7ed 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -348,8 +348,7 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart,
/// factors factored out. If Folded is false, return null if no factoring was
/// possible, to avoid endlessly bouncing an unfoldable expression back into the
/// top-level folder.
-static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
- bool Folded) {
+static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy, bool Folded) {
if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *N = ConstantInt::get(DestTy, ATy->getNumElements());
Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true);
@@ -404,8 +403,7 @@ static Constant *getFoldedSizeOf(Type *Ty, Type *DestTy,
/// factors factored out. If Folded is false, return null if no factoring was
/// possible, to avoid endlessly bouncing an unfoldable expression back into the
/// top-level folder.
-static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy,
- bool Folded) {
+static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy, bool Folded) {
// The alignment of an array is equal to the alignment of the
// array element. Note that this is not always true for vectors.
if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
@@ -469,8 +467,7 @@ static Constant *getFoldedAlignOf(Type *Ty, Type *DestTy,
/// any known factors factored out. If Folded is false, return null if no
/// factoring was possible, to avoid endlessly bouncing an unfoldable expression
/// back into the top-level folder.
-static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo,
- Type *DestTy,
+static Constant *getFoldedOffsetOf(Type *Ty, Constant *FieldNo, Type *DestTy,
bool Folded) {
if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo, false,
diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h
index 6c189cf656de..6585304e7674 100644
--- a/lib/IR/ConstantsContext.h
+++ b/lib/IR/ConstantsContext.h
@@ -55,8 +55,6 @@ public:
return User::operator new(s, 1);
}
- void *operator new(size_t, unsigned) = delete;
-
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@@ -77,8 +75,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@@ -99,8 +95,6 @@ public:
return User::operator new(s, 3);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@@ -122,8 +116,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@@ -146,8 +138,6 @@ public:
return User::operator new(s, 3);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@@ -173,8 +163,6 @@ public:
return User::operator new(s, 3);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
};
@@ -196,8 +184,6 @@ public:
return User::operator new(s, 1);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Indices - These identify which value to extract.
const SmallVector<unsigned, 4> Indices;
@@ -230,8 +216,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Indices - These identify the position for the insertion.
const SmallVector<unsigned, 4> Indices;
@@ -297,8 +281,6 @@ public:
return User::operator new(s, 2);
}
- void *operator new(size_t, unsigned) = delete;
-
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp
index e6c49cad0722..0bf68b4c53bb 100644
--- a/lib/IR/DebugInfoMetadata.cpp
+++ b/lib/IR/DebugInfoMetadata.cpp
@@ -598,8 +598,7 @@ unsigned DIExpression::ExprOperand::getSize() const {
case dwarf::DW_OP_LLVM_fragment:
return 3;
case dwarf::DW_OP_constu:
- case dwarf::DW_OP_plus:
- case dwarf::DW_OP_minus:
+ case dwarf::DW_OP_plus_uconst:
return 2;
default:
return 1;
@@ -641,6 +640,7 @@ bool DIExpression::isValid() const {
break;
}
case dwarf::DW_OP_constu:
+ case dwarf::DW_OP_plus_uconst:
case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus:
case dwarf::DW_OP_deref:
@@ -664,11 +664,12 @@ DIExpression::getFragmentInfo(expr_op_iterator Start, expr_op_iterator End) {
void DIExpression::appendOffset(SmallVectorImpl<uint64_t> &Ops,
int64_t Offset) {
if (Offset > 0) {
- Ops.push_back(dwarf::DW_OP_plus);
+ Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Offset);
} else if (Offset < 0) {
- Ops.push_back(dwarf::DW_OP_minus);
+ Ops.push_back(dwarf::DW_OP_constu);
Ops.push_back(-Offset);
+ Ops.push_back(dwarf::DW_OP_minus);
}
}
@@ -677,16 +678,23 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const {
Offset = 0;
return true;
}
- if (getNumElements() != 2)
- return false;
- if (Elements[0] == dwarf::DW_OP_plus) {
+
+ if (getNumElements() == 2 && Elements[0] == dwarf::DW_OP_plus_uconst) {
Offset = Elements[1];
return true;
}
- if (Elements[0] == dwarf::DW_OP_minus) {
- Offset = -Elements[1];
- return true;
+
+ if (getNumElements() == 3 && Elements[0] == dwarf::DW_OP_constu) {
+ if (Elements[2] == dwarf::DW_OP_plus) {
+ Offset = Elements[1];
+ return true;
+ }
+ if (Elements[2] == dwarf::DW_OP_minus) {
+ Offset = -Elements[1];
+ return true;
+ }
}
+
return false;
}
diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp
index 81b02946e1d5..b7fa07c6ffac 100644
--- a/lib/IR/IRBuilder.cpp
+++ b/lib/IR/IRBuilder.cpp
@@ -134,18 +134,17 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
return CI;
}
-CallInst *IRBuilderBase::CreateElementAtomicMemCpy(
- Value *Dst, Value *Src, Value *NumElements, uint32_t ElementSize,
- MDNode *TBAATag, MDNode *TBAAStructTag, MDNode *ScopeTag,
- MDNode *NoAliasTag) {
+CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(
+ Value *Dst, Value *Src, Value *Size, uint32_t ElementSize, MDNode *TBAATag,
+ MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) {
Dst = getCastedInt8PtrValue(Dst);
Src = getCastedInt8PtrValue(Src);
- Value *Ops[] = {Dst, Src, NumElements, getInt32(ElementSize)};
- Type *Tys[] = {Dst->getType(), Src->getType()};
+ Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)};
+ Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()};
Module *M = BB->getParent()->getParent();
- Value *TheFn =
- Intrinsic::getDeclaration(M, Intrinsic::memcpy_element_atomic, Tys);
+ Value *TheFn = Intrinsic::getDeclaration(
+ M, Intrinsic::memcpy_element_unordered_atomic, Tys);
CallInst *CI = createCallHelper(TheFn, Ops, this);
diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp
index 0b1bc9a8c270..92e5798dcf21 100644
--- a/lib/IR/Metadata.cpp
+++ b/lib/IR/Metadata.cpp
@@ -1470,7 +1470,7 @@ void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) {
if (E)
OrigElements = E->getElements();
std::vector<uint64_t> Elements(OrigElements.size() + 2);
- Elements[0] = dwarf::DW_OP_plus;
+ Elements[0] = dwarf::DW_OP_plus_uconst;
Elements[1] = Offset;
std::copy(OrigElements.begin(), OrigElements.end(), Elements.begin() + 2);
E = DIExpression::get(getContext(), Elements);
diff --git a/lib/IR/ModuleSummaryIndex.cpp b/lib/IR/ModuleSummaryIndex.cpp
index 9dd712f9ca13..51c4bae3332e 100644
--- a/lib/IR/ModuleSummaryIndex.cpp
+++ b/lib/IR/ModuleSummaryIndex.cpp
@@ -56,3 +56,16 @@ ModuleSummaryIndex::getGlobalValueSummary(uint64_t ValueGUID,
auto &Summary = VI.getSummaryList()[0];
return Summary.get();
}
+
+bool ModuleSummaryIndex::isGUIDLive(GlobalValue::GUID GUID) const {
+ auto VI = getValueInfo(GUID);
+ if (!VI)
+ return true;
+ const auto &SummaryList = VI.getSummaryList();
+ if (SummaryList.empty())
+ return true;
+ for (auto &I : SummaryList)
+ if (isGlobalValueLive(I.get()))
+ return true;
+ return false;
+}
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 5c1b3412840d..819f63520c74 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -1330,6 +1330,14 @@ Verifier::visitModuleFlag(const MDNode *Op,
= mdconst::dyn_extract_or_null<ConstantInt>(Op->getOperand(2));
Assert(Value, "wchar_size metadata requires constant integer argument");
}
+
+ if (ID->getString() == "Linker Options") {
+ // If the llvm.linker.options named metadata exists, we assume that the
+ // bitcode reader has upgraded the module flag. Otherwise the flag might
+ // have been created by a client directly.
+ Assert(M.getNamedMetadata("llvm.linker.options"),
+ "'Linker Options' named metadata no longer supported");
+ }
}
/// Return true if this attribute kind only applies to functions.
@@ -4004,10 +4012,16 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
CS);
break;
}
- case Intrinsic::memcpy_element_atomic: {
- ConstantInt *ElementSizeCI = dyn_cast<ConstantInt>(CS.getArgOperand(3));
- Assert(ElementSizeCI, "element size of the element-wise atomic memory "
- "intrinsic must be a constant int",
+ case Intrinsic::memcpy_element_unordered_atomic: {
+ const ElementUnorderedAtomicMemCpyInst *MI =
+ cast<ElementUnorderedAtomicMemCpyInst>(CS.getInstruction());
+ ;
+
+ ConstantInt *ElementSizeCI =
+ dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes());
+ Assert(ElementSizeCI,
+ "element size of the element-wise unordered atomic memory "
+ "intrinsic must be a constant int",
CS);
const APInt &ElementSizeVal = ElementSizeCI->getValue();
Assert(ElementSizeVal.isPowerOf2(),
@@ -4015,19 +4029,24 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
"must be a power of 2",
CS);
+ if (auto *LengthCI = dyn_cast<ConstantInt>(MI->getLength())) {
+ uint64_t Length = LengthCI->getZExtValue();
+ uint64_t ElementSize = MI->getElementSizeInBytes();
+ Assert((Length % ElementSize) == 0,
+ "constant length must be a multiple of the element size in the "
+ "element-wise atomic memory intrinsic",
+ CS);
+ }
+
auto IsValidAlignment = [&](uint64_t Alignment) {
return isPowerOf2_64(Alignment) && ElementSizeVal.ule(Alignment);
};
-
uint64_t DstAlignment = CS.getParamAlignment(0),
SrcAlignment = CS.getParamAlignment(1);
-
Assert(IsValidAlignment(DstAlignment),
- "incorrect alignment of the destination argument",
- CS);
+ "incorrect alignment of the destination argument", CS);
Assert(IsValidAlignment(SrcAlignment),
- "incorrect alignment of the source argument",
- CS);
+ "incorrect alignment of the source argument", CS);
break;
}
case Intrinsic::gcroot:
diff --git a/lib/LLVMBuild.txt b/lib/LLVMBuild.txt
index 9e586465025e..1d22c2a11f13 100644
--- a/lib/LLVMBuild.txt
+++ b/lib/LLVMBuild.txt
@@ -39,6 +39,7 @@ subdirectories =
Support
TableGen
Target
+ Testing
ToolDrivers
Transforms
diff --git a/lib/LTO/LTO.cpp b/lib/LTO/LTO.cpp
index 9d2a44045d6a..35032fdd33e1 100644
--- a/lib/LTO/LTO.cpp
+++ b/lib/LTO/LTO.cpp
@@ -364,31 +364,40 @@ LTO::LTO(Config Conf, ThinBackend Backend,
// Requires a destructor for MapVector<BitcodeModule>.
LTO::~LTO() = default;
-// Add the given symbol to the GlobalResolutions map, and resolve its partition.
-void LTO::addSymbolToGlobalRes(const InputFile::Symbol &Sym,
- SymbolResolution Res, unsigned Partition) {
- auto &GlobalRes = GlobalResolutions[Sym.getName()];
- GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
- if (Res.Prevailing)
- GlobalRes.IRName = Sym.getIRName();
-
- // Set the partition to external if we know it is re-defined by the linker
- // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
- // regular object, is referenced from llvm.compiler_used, or was already
- // recorded as being referenced from a different partition.
- if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
- (GlobalRes.Partition != GlobalResolution::Unknown &&
- GlobalRes.Partition != Partition)) {
- GlobalRes.Partition = GlobalResolution::External;
- } else
- // First recorded reference, save the current partition.
- GlobalRes.Partition = Partition;
-
- // Flag as visible outside of ThinLTO if visible from a regular object or
- // if this is a reference in the regular LTO partition.
- GlobalRes.VisibleOutsideThinLTO |=
- (Res.VisibleToRegularObj || Sym.isUsed() ||
- Partition == GlobalResolution::RegularLTO);
+// Add the symbols in the given module to the GlobalResolutions map, and resolve
+// their partitions.
+void LTO::addModuleToGlobalRes(ArrayRef<InputFile::Symbol> Syms,
+ ArrayRef<SymbolResolution> Res,
+ unsigned Partition, bool InSummary) {
+ auto *ResI = Res.begin();
+ auto *ResE = Res.end();
+ (void)ResE;
+ for (const InputFile::Symbol &Sym : Syms) {
+ assert(ResI != ResE);
+ SymbolResolution Res = *ResI++;
+
+ auto &GlobalRes = GlobalResolutions[Sym.getName()];
+ GlobalRes.UnnamedAddr &= Sym.isUnnamedAddr();
+ if (Res.Prevailing)
+ GlobalRes.IRName = Sym.getIRName();
+
+ // Set the partition to external if we know it is re-defined by the linker
+ // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a
+ // regular object, is referenced from llvm.compiler_used, or was already
+ // recorded as being referenced from a different partition.
+ if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() ||
+ (GlobalRes.Partition != GlobalResolution::Unknown &&
+ GlobalRes.Partition != Partition)) {
+ GlobalRes.Partition = GlobalResolution::External;
+ } else
+ // First recorded reference, save the current partition.
+ GlobalRes.Partition = Partition;
+
+ // Flag as visible outside of summary if visible from a regular object or
+ // from a module that does not have a summary.
+ GlobalRes.VisibleOutsideSummary |=
+ (Res.VisibleToRegularObj || Sym.isUsed() || !InSummary);
+ }
}
static void writeToResolutionFile(raw_ostream &OS, InputFile *Input,
@@ -434,46 +443,61 @@ Error LTO::add(std::unique_ptr<InputFile> Input,
Error LTO::addModule(InputFile &Input, unsigned ModI,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
- Expected<bool> HasThinLTOSummary = Input.Mods[ModI].hasSummary();
- if (!HasThinLTOSummary)
- return HasThinLTOSummary.takeError();
+ Expected<BitcodeLTOInfo> LTOInfo = Input.Mods[ModI].getLTOInfo();
+ if (!LTOInfo)
+ return LTOInfo.takeError();
+ BitcodeModule BM = Input.Mods[ModI];
auto ModSyms = Input.module_symbols(ModI);
- if (*HasThinLTOSummary)
- return addThinLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
- else
- return addRegularLTO(Input.Mods[ModI], ModSyms, ResI, ResE);
+ addModuleToGlobalRes(ModSyms, {ResI, ResE},
+ LTOInfo->IsThinLTO ? ThinLTO.ModuleMap.size() + 1 : 0,
+ LTOInfo->HasSummary);
+
+ if (LTOInfo->IsThinLTO)
+ return addThinLTO(BM, ModSyms, ResI, ResE);
+
+ Expected<RegularLTOState::AddedModule> ModOrErr =
+ addRegularLTO(BM, ModSyms, ResI, ResE);
+ if (!ModOrErr)
+ return ModOrErr.takeError();
+
+ if (!LTOInfo->HasSummary)
+ return linkRegularLTO(std::move(*ModOrErr), /*LivenessFromIndex=*/false);
+
+ // Regular LTO module summaries are added to a dummy module that represents
+ // the combined regular LTO module.
+ if (Error Err = BM.readSummary(ThinLTO.CombinedIndex, "", -1ull))
+ return Err;
+ RegularLTO.ModsWithSummaries.push_back(std::move(*ModOrErr));
+ return Error::success();
}
// Add a regular LTO object to the link.
-Error LTO::addRegularLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
- const SymbolResolution *&ResI,
- const SymbolResolution *ResE) {
- if (!RegularLTO.CombinedModule) {
- RegularLTO.CombinedModule =
- llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
- RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
- }
+// The resulting module needs to be linked into the combined LTO module with
+// linkRegularLTO.
+Expected<LTO::RegularLTOState::AddedModule>
+LTO::addRegularLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
+ const SymbolResolution *&ResI,
+ const SymbolResolution *ResE) {
+ RegularLTOState::AddedModule Mod;
Expected<std::unique_ptr<Module>> MOrErr =
BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true,
/*IsImporting*/ false);
if (!MOrErr)
return MOrErr.takeError();
-
Module &M = **MOrErr;
+ Mod.M = std::move(*MOrErr);
+
if (Error Err = M.materializeMetadata())
- return Err;
+ return std::move(Err);
UpgradeDebugInfo(M);
ModuleSymbolTable SymTab;
SymTab.addModule(&M);
- std::vector<GlobalValue *> Keep;
-
for (GlobalVariable &GV : M.globals())
if (GV.hasAppendingLinkage())
- Keep.push_back(&GV);
+ Mod.Keep.push_back(&GV);
DenseSet<GlobalObject *> AliasedGlobals;
for (auto &GA : M.aliases())
@@ -502,7 +526,6 @@ Error LTO::addRegularLTO(BitcodeModule BM,
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, 0);
assert(MsymI != MsymE);
ModuleSymbolTable::Symbol Msym = *MsymI++;
@@ -512,7 +535,7 @@ Error LTO::addRegularLTO(BitcodeModule BM,
if (Res.Prevailing) {
if (Sym.isUndefined())
continue;
- Keep.push_back(GV);
+ Mod.Keep.push_back(GV);
// For symbols re-defined with linker -wrap and -defsym options,
// set the linkage to weak to inhibit IPO. The linkage will be
// restored by the linker.
@@ -527,17 +550,14 @@ Error LTO::addRegularLTO(BitcodeModule BM,
(GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage() ||
GV->hasAvailableExternallyLinkage()) &&
!AliasedGlobals.count(cast<GlobalObject>(GV))) {
- // Either of the above three types of linkage indicates that the
+ // Any of the above three types of linkage indicates that the
// chosen prevailing symbol will have the same semantics as this copy of
- // the symbol, so we can link it with available_externally linkage. We
- // only need to do this if the symbol is undefined.
- GlobalValue *CombinedGV =
- RegularLTO.CombinedModule->getNamedValue(GV->getName());
- if (!CombinedGV || CombinedGV->isDeclaration()) {
- Keep.push_back(GV);
- GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
- cast<GlobalObject>(GV)->setComdat(nullptr);
- }
+ // the symbol, so we may be able to link it with available_externally
+ // linkage. We will decide later whether to do that when we link this
+ // module (in linkRegularLTO), based on whether it is undefined.
+ Mod.Keep.push_back(GV);
+ GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
+ cast<GlobalObject>(GV)->setComdat(nullptr);
}
}
// Common resolution: collect the maximum size/alignment over all commons.
@@ -555,25 +575,54 @@ Error LTO::addRegularLTO(BitcodeModule BM,
// FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
}
assert(MsymI == MsymE);
+ return std::move(Mod);
+}
+
+Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod,
+ bool LivenessFromIndex) {
+ if (!RegularLTO.CombinedModule) {
+ RegularLTO.CombinedModule =
+ llvm::make_unique<Module>("ld-temp.o", RegularLTO.Ctx);
+ RegularLTO.Mover = llvm::make_unique<IRMover>(*RegularLTO.CombinedModule);
+ }
+
+ std::vector<GlobalValue *> Keep;
+ for (GlobalValue *GV : Mod.Keep) {
+ if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID()))
+ continue;
- return RegularLTO.Mover->move(std::move(*MOrErr), Keep,
+ if (!GV->hasAvailableExternallyLinkage()) {
+ Keep.push_back(GV);
+ continue;
+ }
+
+ // Only link available_externally definitions if we don't already have a
+ // definition.
+ GlobalValue *CombinedGV =
+ RegularLTO.CombinedModule->getNamedValue(GV->getName());
+ if (CombinedGV && !CombinedGV->isDeclaration())
+ continue;
+
+ Keep.push_back(GV);
+ }
+
+ return RegularLTO.Mover->move(std::move(Mod.M), Keep,
[](GlobalValue &, IRMover::ValueAdder) {},
/* IsPerformingImport */ false);
}
-// Add a ThinLTO object to the link.
-Error LTO::addThinLTO(BitcodeModule BM,
- ArrayRef<InputFile::Symbol> Syms,
+// Add a ThinLTO module to the link.
+Error LTO::addThinLTO(BitcodeModule BM, ArrayRef<InputFile::Symbol> Syms,
const SymbolResolution *&ResI,
const SymbolResolution *ResE) {
if (Error Err =
- BM.readSummary(ThinLTO.CombinedIndex, ThinLTO.ModuleMap.size()))
+ BM.readSummary(ThinLTO.CombinedIndex, BM.getModuleIdentifier(),
+ ThinLTO.ModuleMap.size()))
return Err;
for (const InputFile::Symbol &Sym : Syms) {
assert(ResI != ResE);
SymbolResolution Res = *ResI++;
- addSymbolToGlobalRes(Sym, Res, ThinLTO.ModuleMap.size() + 1);
if (Res.Prevailing) {
if (!Sym.getIRName().empty()) {
@@ -601,7 +650,7 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
// Compute "dead" symbols, we don't want to import/export these!
DenseSet<GlobalValue::GUID> GUIDPreservedSymbols;
for (auto &Res : GlobalResolutions) {
- if (Res.second.VisibleOutsideThinLTO &&
+ if (Res.second.VisibleOutsideSummary &&
// IRName will be defined if we have seen the prevailing copy of
// this value. If not, no need to preserve any ThinLTO copies.
!Res.second.IRName.empty())
@@ -614,7 +663,8 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
// Save the status of having a regularLTO combined module, as
// this is needed for generating the ThinLTO Task ID, and
// the CombinedModule will be moved at the end of runRegularLTO.
- bool HasRegularLTO = RegularLTO.CombinedModule != nullptr;
+ bool HasRegularLTO = RegularLTO.CombinedModule != nullptr ||
+ !RegularLTO.ModsWithSummaries.empty();
// Invoke regular LTO if there was a regular LTO module to start with.
if (HasRegularLTO)
if (auto E = runRegularLTO(AddStream))
@@ -623,6 +673,11 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
}
Error LTO::runRegularLTO(AddStreamFn AddStream) {
+ for (auto &M : RegularLTO.ModsWithSummaries)
+ if (Error Err = linkRegularLTO(std::move(M),
+ /*LivenessFromIndex=*/true))
+ return Err;
+
// Make sure commons have the right size/alignment: we kept the largest from
// all the prevailing when adding the inputs, and we apply it here.
const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
@@ -920,17 +975,6 @@ ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
};
}
-static bool IsLiveByGUID(const ModuleSummaryIndex &Index,
- GlobalValue::GUID GUID) {
- auto VI = Index.getValueInfo(GUID);
- if (!VI)
- return false;
- for (auto &I : VI.getSummaryList())
- if (Index.isGlobalValueLive(I.get()))
- return true;
- return false;
-}
-
Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
bool HasRegularLTO) {
if (ThinLTO.ModuleMap.empty())
@@ -979,7 +1023,7 @@ Error LTO::runThinLTO(AddStreamFn AddStream, NativeObjectCache Cache,
auto GUID = GlobalValue::getGUID(
GlobalValue::dropLLVMManglingEscape(Res.second.IRName));
// Mark exported unless index-based analysis determined it to be dead.
- if (IsLiveByGUID(ThinLTO.CombinedIndex, GUID))
+ if (ThinLTO.CombinedIndex.isGUIDLive(GUID))
ExportedGUIDs.insert(GUID);
}
diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp
index 11f0982c6a60..3cc8b7d0e770 100644
--- a/lib/LTO/LTOModule.cpp
+++ b/lib/LTO/LTOModule.cpp
@@ -77,14 +77,12 @@ bool LTOModule::isBitcodeFile(StringRef Path) {
}
bool LTOModule::isThinLTO() {
- // Right now the detection is only based on the summary presence. We may want
- // to add a dedicated flag at some point.
- Expected<bool> Result = hasGlobalValueSummary(MBRef);
+ Expected<BitcodeLTOInfo> Result = getBitcodeLTOInfo(MBRef);
if (!Result) {
logAllUnhandledErrors(Result.takeError(), errs(), "");
return false;
}
- return *Result;
+ return Result->IsThinLTO;
}
bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer,
@@ -637,10 +635,10 @@ void LTOModule::parseMetadata() {
raw_string_ostream OS(LinkerOpts);
// Linker Options
- if (Metadata *Val = getModule().getModuleFlag("Linker Options")) {
- MDNode *LinkerOptions = cast<MDNode>(Val);
+ if (NamedMDNode *LinkerOptions =
+ getModule().getNamedMetadata("llvm.linker.options")) {
for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
- MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
+ MDNode *MDOptions = LinkerOptions->getOperand(i);
for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) {
MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii));
OS << " " << MDOption->getString();
diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp
index f1dfb91aafbb..a407691b0bd1 100644
--- a/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/lib/MC/MCParser/ELFAsmParser.cpp
@@ -603,6 +603,8 @@ EndStmt:
Type = ELF::SHT_NOTE;
else if (TypeName == "unwind")
Type = ELF::SHT_X86_64_UNWIND;
+ else if (TypeName == "llvm_odrtab")
+ Type = ELF::SHT_LLVM_ODRTAB;
else if (TypeName.getAsInteger(0, Type))
return TokError("unknown section type");
}
diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp
index a75068ebf05a..2f4f61aa4d50 100644
--- a/lib/MC/MCSectionELF.cpp
+++ b/lib/MC/MCSectionELF.cpp
@@ -147,6 +147,8 @@ void MCSectionELF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
// Print hex value of the flag while we do not have
// any standard symbolic representation of the flag.
OS << "0x7000001e";
+ else if (Type == ELF::SHT_LLVM_ODRTAB)
+ OS << "llvm_odrtab";
else
report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
" for section " + getSectionName());
diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp
index 4b3dc6e0c211..db304c027f99 100644
--- a/lib/MC/WasmObjectWriter.cpp
+++ b/lib/MC/WasmObjectWriter.cpp
@@ -181,7 +181,10 @@ class WasmObjectWriter : public MCObjectWriter {
// Index values to use for fixing up call_indirect type indices.
// Maps function symbols to the index of the type of the function
DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
-
+ // Maps function symbols to the table element index space. Used
+ // for TABLE_INDEX relocation types (i.e. address taken functions).
+ DenseMap<const MCSymbolWasm *, uint32_t> IndirectSymbolIndices;
+ // Maps function/global symbols to the function/global index space.
DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices;
DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
@@ -189,9 +192,8 @@ class WasmObjectWriter : public MCObjectWriter {
// TargetObjectWriter wrappers.
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
- unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
- const MCFixup &Fixup, bool IsPCRel) const {
- return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
+ unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const {
+ return TargetObjectWriter->getRelocType(Target, Fixup);
}
void startSection(SectionBookkeeping &Section, unsigned SectionId,
@@ -210,6 +212,7 @@ private:
DataRelocations.clear();
TypeIndices.clear();
SymbolIndices.clear();
+ IndirectSymbolIndices.clear();
FunctionTypeIndices.clear();
MCObjectWriter::reset();
}
@@ -233,7 +236,7 @@ private:
void writeTypeSection(const SmallVector<WasmFunctionType, 4> &FunctionTypes);
void writeImportSection(const SmallVector<WasmImport, 4> &Imports);
void writeFunctionSection(const SmallVector<WasmFunction, 4> &Functions);
- void writeTableSection(const SmallVector<uint32_t, 4> &TableElems);
+ void writeTableSection(uint32_t NumElements);
void writeMemorySection(const SmallVector<char, 0> &DataBytes);
void writeGlobalSection(const SmallVector<WasmGlobal, 4> &Globals);
void writeExportSection(const SmallVector<WasmExport, 4> &Exports);
@@ -402,7 +405,9 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
SymA->setUsedInReloc();
}
- unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel);
+ assert(!IsPCRel);
+ unsigned Type = getRelocType(Target, Fixup);
+
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
if (FixupSection.hasInstructions())
@@ -464,9 +469,11 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
uint32_t WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
switch (RelEntry.Type) {
- case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+ assert(IndirectSymbolIndices.count(RelEntry.Symbol));
+ return IndirectSymbolIndices[RelEntry.Symbol];
+ case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
@@ -617,21 +624,19 @@ void WasmObjectWriter::writeFunctionSection(
endSection(Section);
}
-void WasmObjectWriter::writeTableSection(
- const SmallVector<uint32_t, 4> &TableElems) {
+void WasmObjectWriter::writeTableSection(uint32_t NumElements) {
// For now, always emit the table section, since indirect calls are not
// valid without it. In the future, we could perhaps be more clever and omit
// it if there are no indirect calls.
+
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_TABLE);
- // The number of tables, fixed to 1 for now.
- encodeULEB128(1, getStream());
-
- encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream());
-
- encodeULEB128(0, getStream()); // flags
- encodeULEB128(TableElems.size(), getStream()); // initial
+ encodeULEB128(1, getStream()); // The number of tables.
+ // Fixed to 1 for now.
+ encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table
+ encodeULEB128(0, getStream()); // flags
+ encodeULEB128(NumElements, getStream()); // initial
endSection(Section);
}
@@ -1072,8 +1077,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
}
// If needed, prepare the function to be called indirectly.
- if (IsAddressTaken.count(&WS))
+ if (IsAddressTaken.count(&WS)) {
+ IndirectSymbolIndices[&WS] = TableElems.size();
TableElems.push_back(Index);
+ }
} else {
if (WS.isTemporary() && !WS.getSize())
continue;
@@ -1180,7 +1187,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeTypeSection(FunctionTypes);
writeImportSection(Imports);
writeFunctionSection(Functions);
- writeTableSection(TableElems);
+ writeTableSection(TableElems.size());
writeMemorySection(DataBytes);
writeGlobalSection(Globals);
writeExportSection(Exports);
diff --git a/lib/Object/ArchiveWriter.cpp b/lib/Object/ArchiveWriter.cpp
index e1c35ed6a6a0..4034f9039dda 100644
--- a/lib/Object/ArchiveWriter.cpp
+++ b/lib/Object/ArchiveWriter.cpp
@@ -36,7 +36,8 @@
using namespace llvm;
NewArchiveMember::NewArchiveMember(MemoryBufferRef BufRef)
- : Buf(MemoryBuffer::getMemBuffer(BufRef, false)) {}
+ : Buf(MemoryBuffer::getMemBuffer(BufRef, false)),
+ MemberName(BufRef.getBufferIdentifier()) {}
Expected<NewArchiveMember>
NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
@@ -48,6 +49,7 @@ NewArchiveMember::getOldMember(const object::Archive::Child &OldMember,
NewArchiveMember M;
assert(M.IsNew == false);
M.Buf = MemoryBuffer::getMemBuffer(*BufOrErr, false);
+ M.MemberName = M.Buf->getBufferIdentifier();
if (!Deterministic) {
auto ModTimeOrErr = OldMember.getLastModified();
if (!ModTimeOrErr)
@@ -97,6 +99,7 @@ Expected<NewArchiveMember> NewArchiveMember::getFile(StringRef FileName,
NewArchiveMember M;
M.IsNew = true;
M.Buf = std::move(*MemberBufferOrErr);
+ M.MemberName = M.Buf->getBufferIdentifier();
if (!Deterministic) {
M.ModTime = std::chrono::time_point_cast<std::chrono::seconds>(
Status.getLastModificationTime());
@@ -185,7 +188,7 @@ printBSDMemberHeader(raw_fd_ostream &Out, StringRef Name,
}
static bool useStringTable(bool Thin, StringRef Name) {
- return Thin || Name.size() >= 16;
+ return Thin || Name.size() >= 16 || Name.contains('/');
}
static void
@@ -239,7 +242,7 @@ static void writeStringTable(raw_fd_ostream &Out, StringRef ArcName,
unsigned StartOffset = 0;
for (const NewArchiveMember &M : Members) {
StringRef Path = M.Buf->getBufferIdentifier();
- StringRef Name = sys::path::filename(Path);
+ StringRef Name = M.MemberName;
if (!useStringTable(Thin, Name))
continue;
if (StartOffset == 0) {
@@ -423,9 +426,8 @@ llvm::writeArchive(StringRef ArcName,
if (Kind == object::Archive::K_DARWIN)
Padding = OffsetToAlignment(M.Buf->getBufferSize(), 8);
- printMemberHeader(Out, Kind, Thin,
- sys::path::filename(M.Buf->getBufferIdentifier()),
- StringMapIndexIter, M.ModTime, M.UID, M.GID, M.Perms,
+ printMemberHeader(Out, Kind, Thin, M.MemberName, StringMapIndexIter,
+ M.ModTime, M.UID, M.GID, M.Perms,
M.Buf->getBufferSize() + Padding);
if (!Thin)
diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp
index 9bc28dc14a29..448fb1bd6b56 100644
--- a/lib/Object/ELF.cpp
+++ b/lib/Object/ELF.cpp
@@ -192,6 +192,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
STRINGIFY_ENUM_CASE(ELF, SHT_PREINIT_ARRAY);
STRINGIFY_ENUM_CASE(ELF, SHT_GROUP);
STRINGIFY_ENUM_CASE(ELF, SHT_SYMTAB_SHNDX);
+ STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef);
diff --git a/lib/Object/IRSymtab.cpp b/lib/Object/IRSymtab.cpp
index d21acdb1d556..a6cd5dda12d3 100644
--- a/lib/Object/IRSymtab.cpp
+++ b/lib/Object/IRSymtab.cpp
@@ -109,9 +109,9 @@ Error Builder::addModule(Module *M) {
if (TT.isOSBinFormatCOFF()) {
if (auto E = M->materializeMetadata())
return E;
- if (Metadata *Val = M->getModuleFlag("Linker Options")) {
- MDNode *LinkerOptions = cast<MDNode>(Val);
- for (const MDOperand &MDOptions : LinkerOptions->operands())
+ if (NamedMDNode *LinkerOptions =
+ M->getNamedMetadata("llvm.linker.options")) {
+ for (MDNode *MDOptions : LinkerOptions->operands())
for (const MDOperand &MDOption : cast<MDNode>(MDOptions)->operands())
COFFLinkerOptsOS << " " << cast<MDString>(MDOption)->getString();
}
diff --git a/lib/Object/WindowsResource.cpp b/lib/Object/WindowsResource.cpp
index 041659e7aa23..3f6080d48f9d 100644
--- a/lib/Object/WindowsResource.cpp
+++ b/lib/Object/WindowsResource.cpp
@@ -30,6 +30,10 @@ namespace object {
const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t);
+// COFF files seem to be inconsistent with alignment between sections, just use
+// 8-byte because it makes everyone happy.
+const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t);
+
static const size_t ResourceMagicSize = 16;
static const size_t NullEntrySize = 16;
@@ -66,7 +70,7 @@ ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref,
const WindowsResource *Owner, Error &Err)
: Reader(Ref), OwningRes(Owner) {
if (loadNext())
- Err = make_error<GenericBinaryError>("Could not read first entry.",
+ Err = make_error<GenericBinaryError>("Could not read first entry.\n",
object_error::unexpected_eof);
}
@@ -133,31 +137,35 @@ Error WindowsResourceParser::parse(WindowsResource *WR) {
ResourceEntryRef Entry = EntryOrErr.get();
bool End = false;
while (!End) {
-
Data.push_back(Entry.getData());
- if (Entry.checkTypeString())
+ bool IsNewTypeString = false;
+ bool IsNewNameString = false;
+
+ Root.addEntry(Entry, IsNewTypeString, IsNewNameString);
+
+ if (IsNewTypeString)
StringTable.push_back(Entry.getTypeString());
- if (Entry.checkNameString())
+ if (IsNewNameString)
StringTable.push_back(Entry.getNameString());
- Root.addEntry(Entry);
-
RETURN_IF_ERROR(Entry.moveNext(End));
}
return Error::success();
}
-void WindowsResourceParser::printTree() const {
- ScopedPrinter Writer(outs());
+void WindowsResourceParser::printTree(raw_ostream &OS) const {
+ ScopedPrinter Writer(OS);
Root.print(Writer, "Resource Tree");
}
-void WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry) {
- TreeNode &TypeNode = addTypeNode(Entry);
- TreeNode &NameNode = TypeNode.addNameNode(Entry);
+void WindowsResourceParser::TreeNode::addEntry(const ResourceEntryRef &Entry,
+ bool &IsNewTypeString,
+ bool &IsNewNameString) {
+ TreeNode &TypeNode = addTypeNode(Entry, IsNewTypeString);
+ TreeNode &NameNode = TypeNode.addNameNode(Entry, IsNewNameString);
NameNode.addLanguageNode(Entry);
}
@@ -171,7 +179,6 @@ WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion,
uint32_t Characteristics)
: IsDataNode(true), MajorVersion(MajorVersion), MinorVersion(MinorVersion),
Characteristics(Characteristics) {
- if (IsDataNode)
DataIndex = DataCount++;
}
@@ -194,17 +201,19 @@ WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion,
}
WindowsResourceParser::TreeNode &
-WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry) {
+WindowsResourceParser::TreeNode::addTypeNode(const ResourceEntryRef &Entry,
+ bool &IsNewTypeString) {
if (Entry.checkTypeString())
- return addChild(Entry.getTypeString());
+ return addChild(Entry.getTypeString(), IsNewTypeString);
else
return addChild(Entry.getTypeID());
}
WindowsResourceParser::TreeNode &
-WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry) {
+WindowsResourceParser::TreeNode::addNameNode(const ResourceEntryRef &Entry,
+ bool &IsNewNameString) {
if (Entry.checkNameString())
- return addChild(Entry.getNameString());
+ return addChild(Entry.getNameString(), IsNewNameString);
else
return addChild(Entry.getNameID());
}
@@ -232,7 +241,8 @@ WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addChild(
}
WindowsResourceParser::TreeNode &
-WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef) {
+WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef,
+ bool &IsNewString) {
std::string NameString;
ArrayRef<UTF16> CorrectedName;
std::vector<UTF16> EndianCorrectedName;
@@ -248,6 +258,7 @@ WindowsResourceParser::TreeNode::addChild(ArrayRef<UTF16> NameRef) {
auto Child = StringChildren.find(NameString);
if (Child == StringChildren.end()) {
auto NewChild = createStringNode();
+ IsNewString = true;
WindowsResourceParser::TreeNode &Node = *NewChild;
StringChildren.emplace(NameString, std::move(NewChild));
return Node;
@@ -296,7 +307,6 @@ class WindowsResourceCOFFWriter {
public:
WindowsResourceCOFFWriter(StringRef OutputFile, Machine MachineType,
const WindowsResourceParser &Parser, Error &E);
-
Error write();
private:
@@ -314,7 +324,8 @@ private:
void writeDirectoryStringTable();
void writeFirstSectionRelocations();
std::unique_ptr<FileOutputBuffer> Buffer;
- uint8_t *Current;
+ uint8_t *BufferStart;
+ uint64_t CurrentOffset = 0;
Machine MachineType;
const WindowsResourceParser::TreeNode &Resources;
const ArrayRef<std::vector<uint8_t>> Data;
@@ -386,6 +397,7 @@ void WindowsResourceCOFFWriter::performSectionOneLayout() {
FileSize += SectionOneSize;
FileSize += Data.size() *
llvm::COFF::RelocationSize; // one relocation for each resource.
+ FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
}
void WindowsResourceCOFFWriter::performSectionTwoLayout() {
@@ -398,6 +410,7 @@ void WindowsResourceCOFFWriter::performSectionTwoLayout() {
SectionTwoSize += llvm::alignTo(Entry.size(), sizeof(uint64_t));
}
FileSize += SectionTwoSize;
+ FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
}
static std::time_t getTime() {
@@ -408,7 +421,7 @@ static std::time_t getTime() {
}
Error WindowsResourceCOFFWriter::write() {
- Current = Buffer->getBufferStart();
+ BufferStart = Buffer->getBufferStart();
writeCOFFHeader();
writeFirstSectionHeader();
@@ -427,7 +440,8 @@ Error WindowsResourceCOFFWriter::write() {
void WindowsResourceCOFFWriter::writeCOFFHeader() {
// Write the COFF header.
- auto *Header = reinterpret_cast<llvm::object::coff_file_header *>(Current);
+ auto *Header =
+ reinterpret_cast<llvm::object::coff_file_header *>(BufferStart);
switch (MachineType) {
case Machine::ARM:
Header->Machine = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
@@ -452,9 +466,9 @@ void WindowsResourceCOFFWriter::writeCOFFHeader() {
void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
// Write the first section header.
- Current += sizeof(llvm::object::coff_file_header);
- auto *SectionOneHeader =
- reinterpret_cast<llvm::object::coff_section *>(Current);
+ CurrentOffset += sizeof(llvm::object::coff_file_header);
+ auto *SectionOneHeader = reinterpret_cast<llvm::object::coff_section *>(
+ BufferStart + CurrentOffset);
strncpy(SectionOneHeader->Name, ".rsrc$01", (size_t)llvm::COFF::NameSize);
SectionOneHeader->VirtualSize = 0;
SectionOneHeader->VirtualAddress = 0;
@@ -473,9 +487,9 @@ void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
// Write the second section header.
- Current += sizeof(llvm::object::coff_section);
- auto *SectionTwoHeader =
- reinterpret_cast<llvm::object::coff_section *>(Current);
+ CurrentOffset += sizeof(llvm::object::coff_section);
+ auto *SectionTwoHeader = reinterpret_cast<llvm::object::coff_section *>(
+ BufferStart + CurrentOffset);
strncpy(SectionTwoHeader->Name, ".rsrc$02", (size_t)llvm::COFF::NameSize);
SectionTwoHeader->VirtualSize = 0;
SectionTwoHeader->VirtualAddress = 0;
@@ -492,75 +506,85 @@ void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
void WindowsResourceCOFFWriter::writeFirstSection() {
// Write section one.
- Current += sizeof(llvm::object::coff_section);
+ CurrentOffset += sizeof(llvm::object::coff_section);
writeDirectoryTree();
writeDirectoryStringTable();
writeFirstSectionRelocations();
+
+ CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT);
}
void WindowsResourceCOFFWriter::writeSecondSection() {
// Now write the .rsrc$02 section.
for (auto const &RawDataEntry : Data) {
- std::copy(RawDataEntry.begin(), RawDataEntry.end(), Current);
- Current += alignTo(RawDataEntry.size(), sizeof(uint64_t));
+ std::copy(RawDataEntry.begin(), RawDataEntry.end(),
+ BufferStart + CurrentOffset);
+ CurrentOffset += alignTo(RawDataEntry.size(), sizeof(uint64_t));
}
+
+ CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT);
}
void WindowsResourceCOFFWriter::writeSymbolTable() {
// Now write the symbol table.
// First, the feat symbol.
- auto *Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
+ auto *Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
strncpy(Symbol->Name.ShortName, "@feat.00", (size_t)llvm::COFF::NameSize);
Symbol->Value = 0x11;
Symbol->SectionNumber = 0xffff;
Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 0;
- Current += sizeof(llvm::object::coff_symbol16);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
// Now write the .rsrc1 symbol + aux.
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
+ Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
strncpy(Symbol->Name.ShortName, ".rsrc$01", (size_t)llvm::COFF::NameSize);
Symbol->Value = 0;
Symbol->SectionNumber = 1;
Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 1;
- Current += sizeof(llvm::object::coff_symbol16);
- auto *Aux =
- reinterpret_cast<llvm::object::coff_aux_section_definition *>(Current);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
+ auto *Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(
+ BufferStart + CurrentOffset);
Aux->Length = SectionOneSize;
Aux->NumberOfRelocations = Data.size();
Aux->NumberOfLinenumbers = 0;
Aux->CheckSum = 0;
Aux->NumberLowPart = 0;
Aux->Selection = 0;
- Current += sizeof(llvm::object::coff_aux_section_definition);
+ CurrentOffset += sizeof(llvm::object::coff_aux_section_definition);
// Now write the .rsrc2 symbol + aux.
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
+ Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
strncpy(Symbol->Name.ShortName, ".rsrc$02", (size_t)llvm::COFF::NameSize);
Symbol->Value = 0;
Symbol->SectionNumber = 2;
Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 1;
- Current += sizeof(llvm::object::coff_symbol16);
- Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(Current);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
+ Aux = reinterpret_cast<llvm::object::coff_aux_section_definition *>(
+ BufferStart + CurrentOffset);
Aux->Length = SectionTwoSize;
Aux->NumberOfRelocations = 0;
Aux->NumberOfLinenumbers = 0;
Aux->CheckSum = 0;
Aux->NumberLowPart = 0;
Aux->Selection = 0;
- Current += sizeof(llvm::object::coff_aux_section_definition);
+ CurrentOffset += sizeof(llvm::object::coff_aux_section_definition);
// Now write a symbol for each relocation.
for (unsigned i = 0; i < Data.size(); i++) {
char RelocationName[9];
sprintf(RelocationName, "$R%06X", DataOffsets[i]);
- Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(Current);
+ Symbol = reinterpret_cast<llvm::object::coff_symbol16 *>(BufferStart +
+ CurrentOffset);
strncpy(Symbol->Name.ShortName, RelocationName,
(size_t)llvm::COFF::NameSize);
Symbol->Value = DataOffsets[i];
@@ -568,14 +592,14 @@ void WindowsResourceCOFFWriter::writeSymbolTable() {
Symbol->Type = llvm::COFF::IMAGE_SYM_DTYPE_NULL;
Symbol->StorageClass = llvm::COFF::IMAGE_SYM_CLASS_STATIC;
Symbol->NumberOfAuxSymbols = 0;
- Current += sizeof(llvm::object::coff_symbol16);
+ CurrentOffset += sizeof(llvm::object::coff_symbol16);
}
}
void WindowsResourceCOFFWriter::writeStringTable() {
// Just 4 null bytes for the string table.
- auto COFFStringTable = reinterpret_cast<uint32_t *>(Current);
- *COFFStringTable = 0;
+ auto COFFStringTable = reinterpret_cast<void *>(BufferStart + CurrentOffset);
+ memset(COFFStringTable, 0, 4);
}
void WindowsResourceCOFFWriter::writeDirectoryTree() {
@@ -593,8 +617,8 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
while (!Queue.empty()) {
auto CurrentNode = Queue.front();
Queue.pop();
- auto *Table =
- reinterpret_cast<llvm::object::coff_resource_dir_table *>(Current);
+ auto *Table = reinterpret_cast<llvm::object::coff_resource_dir_table *>(
+ BufferStart + CurrentOffset);
Table->Characteristics = CurrentNode->getCharacteristics();
Table->TimeDateStamp = 0;
Table->MajorVersion = CurrentNode->getMajorVersion();
@@ -603,13 +627,13 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
auto &StringChildren = CurrentNode->getStringChildren();
Table->NumberOfNameEntries = StringChildren.size();
Table->NumberOfIDEntries = IDChildren.size();
- Current += sizeof(llvm::object::coff_resource_dir_table);
+ CurrentOffset += sizeof(llvm::object::coff_resource_dir_table);
CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_table);
// Write the directory entries immediately following each directory table.
for (auto const &Child : StringChildren) {
- auto *Entry =
- reinterpret_cast<llvm::object::coff_resource_dir_entry *>(Current);
+ auto *Entry = reinterpret_cast<llvm::object::coff_resource_dir_entry *>(
+ BufferStart + CurrentOffset);
Entry->Identifier.NameOffset =
StringTableOffsets[Child.second->getStringIndex()];
if (Child.second->checkIsDataNode()) {
@@ -624,12 +648,12 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
sizeof(llvm::object::coff_resource_dir_entry);
Queue.push(Child.second.get());
}
- Current += sizeof(llvm::object::coff_resource_dir_entry);
+ CurrentOffset += sizeof(llvm::object::coff_resource_dir_entry);
CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry);
}
for (auto const &Child : IDChildren) {
- auto *Entry =
- reinterpret_cast<llvm::object::coff_resource_dir_entry *>(Current);
+ auto *Entry = reinterpret_cast<llvm::object::coff_resource_dir_entry *>(
+ BufferStart + CurrentOffset);
Entry->Identifier.ID = Child.first;
if (Child.second->checkIsDataNode()) {
Entry->Offset.DataEntryOffset = NextLevelOffset;
@@ -643,7 +667,7 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
sizeof(llvm::object::coff_resource_dir_entry);
Queue.push(Child.second.get());
}
- Current += sizeof(llvm::object::coff_resource_dir_entry);
+ CurrentOffset += sizeof(llvm::object::coff_resource_dir_entry);
CurrentRelativeOffset += sizeof(llvm::object::coff_resource_dir_entry);
}
}
@@ -651,14 +675,14 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
RelocationAddresses.resize(Data.size());
// Now write all the resource data entries.
for (auto DataNodes : DataEntriesTreeOrder) {
- auto *Entry =
- reinterpret_cast<llvm::object::coff_resource_data_entry *>(Current);
+ auto *Entry = reinterpret_cast<llvm::object::coff_resource_data_entry *>(
+ BufferStart + CurrentOffset);
RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset;
Entry->DataRVA = 0; // Set to zero because it is a relocation.
Entry->DataSize = Data[DataNodes->getDataIndex()].size();
Entry->Codepage = 0;
Entry->Reserved = 0;
- Current += sizeof(llvm::object::coff_resource_data_entry);
+ CurrentOffset += sizeof(llvm::object::coff_resource_data_entry);
CurrentRelativeOffset += sizeof(llvm::object::coff_resource_data_entry);
}
}
@@ -666,17 +690,16 @@ void WindowsResourceCOFFWriter::writeDirectoryTree() {
void WindowsResourceCOFFWriter::writeDirectoryStringTable() {
// Now write the directory string table for .rsrc$01
uint32_t TotalStringTableSize = 0;
- for (auto String : StringTable) {
- auto *LengthField = reinterpret_cast<uint16_t *>(Current);
+ for (auto &String : StringTable) {
uint16_t Length = String.size();
- *LengthField = Length;
- Current += sizeof(uint16_t);
- auto *Start = reinterpret_cast<UTF16 *>(Current);
+ support::endian::write16le(BufferStart + CurrentOffset, Length);
+ CurrentOffset += sizeof(uint16_t);
+ auto *Start = reinterpret_cast<UTF16 *>(BufferStart + CurrentOffset);
std::copy(String.begin(), String.end(), Start);
- Current += Length * sizeof(UTF16);
+ CurrentOffset += Length * sizeof(UTF16);
TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t);
}
- Current +=
+ CurrentOffset +=
alignTo(TotalStringTableSize, sizeof(uint32_t)) - TotalStringTableSize;
}
@@ -687,7 +710,8 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
// .rsrc section.
uint32_t NextSymbolIndex = 5;
for (unsigned i = 0; i < Data.size(); i++) {
- auto *Reloc = reinterpret_cast<llvm::object::coff_relocation *>(Current);
+ auto *Reloc = reinterpret_cast<llvm::object::coff_relocation *>(
+ BufferStart + CurrentOffset);
Reloc->VirtualAddress = RelocationAddresses[i];
Reloc->SymbolTableIndex = NextSymbolIndex++;
switch (MachineType) {
@@ -703,7 +727,7 @@ void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {
default:
Reloc->Type = 0;
}
- Current += sizeof(llvm::object::coff_relocation);
+ CurrentOffset += sizeof(llvm::object::coff_relocation);
}
}
diff --git a/lib/ObjectYAML/COFFYAML.cpp b/lib/ObjectYAML/COFFYAML.cpp
index 7f9f4c1f8c2c..c8cbea1490f6 100644
--- a/lib/ObjectYAML/COFFYAML.cpp
+++ b/lib/ObjectYAML/COFFYAML.cpp
@@ -488,7 +488,16 @@ void MappingTraits<COFFYAML::Section>::mapping(IO &IO, COFFYAML::Section &Sec) {
IO.mapOptional("VirtualAddress", Sec.Header.VirtualAddress, 0U);
IO.mapOptional("VirtualSize", Sec.Header.VirtualSize, 0U);
IO.mapOptional("Alignment", Sec.Alignment, 0U);
- IO.mapRequired("SectionData", Sec.SectionData);
+
+ // If this is a .debug$S or .debug$T section parse the semantic representation
+ // of the symbols/types. If it is any other kind of section, just deal in raw
+ // bytes.
+ IO.mapOptional("SectionData", Sec.SectionData);
+ if (Sec.Name == ".debug$S")
+ IO.mapOptional("Subsections", Sec.DebugS);
+ else if (Sec.Name == ".debug$T")
+ IO.mapOptional("Types", Sec.DebugT);
+
IO.mapOptional("Relocations", Sec.Relocations);
}
diff --git a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
index 08a4bb715fac..d194420d5ef4 100644
--- a/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
+++ b/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
@@ -28,6 +28,7 @@
#include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
@@ -75,10 +76,9 @@ struct YAMLSubsectionBase {
virtual ~YAMLSubsectionBase() {}
virtual void map(IO &IO) = 0;
- virtual std::unique_ptr<DebugSubsection>
+ virtual std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *UseStrings,
- DebugChecksumsSubsection *UseChecksums) const = 0;
+ const codeview::StringsAndChecksums &SC) const = 0;
};
}
}
@@ -90,10 +90,9 @@ struct YAMLChecksumsSubsection : public YAMLSubsectionBase {
: YAMLSubsectionBase(DebugSubsectionKind::FileChecksums) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLChecksumsSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
const DebugChecksumsSubsectionRef &FC);
@@ -105,10 +104,9 @@ struct YAMLLinesSubsection : public YAMLSubsectionBase {
YAMLLinesSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Lines) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLLinesSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
const DebugChecksumsSubsectionRef &Checksums,
@@ -122,10 +120,9 @@ struct YAMLInlineeLinesSubsection : public YAMLSubsectionBase {
: YAMLSubsectionBase(DebugSubsectionKind::InlineeLines) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLInlineeLinesSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
const DebugChecksumsSubsectionRef &Checksums,
@@ -139,10 +136,9 @@ struct YAMLCrossModuleExportsSubsection : public YAMLSubsectionBase {
: YAMLSubsectionBase(DebugSubsectionKind::CrossScopeExports) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLCrossModuleExportsSubsection>>
fromCodeViewSubsection(const DebugCrossModuleExportsSubsectionRef &Exports);
@@ -154,10 +150,9 @@ struct YAMLCrossModuleImportsSubsection : public YAMLSubsectionBase {
: YAMLSubsectionBase(DebugSubsectionKind::CrossScopeImports) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLCrossModuleImportsSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
const DebugCrossModuleImportsSubsectionRef &Imports);
@@ -169,10 +164,9 @@ struct YAMLSymbolsSubsection : public YAMLSubsectionBase {
YAMLSymbolsSubsection() : YAMLSubsectionBase(DebugSubsectionKind::Symbols) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLSymbolsSubsection>>
fromCodeViewSubsection(const DebugSymbolsSubsectionRef &Symbols);
@@ -184,10 +178,9 @@ struct YAMLStringTableSubsection : public YAMLSubsectionBase {
: YAMLSubsectionBase(DebugSubsectionKind::StringTable) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLStringTableSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings);
@@ -199,10 +192,9 @@ struct YAMLFrameDataSubsection : public YAMLSubsectionBase {
: YAMLSubsectionBase(DebugSubsectionKind::FrameData) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLFrameDataSubsection>>
fromCodeViewSubsection(const DebugStringTableSubsectionRef &Strings,
const DebugFrameDataSubsectionRef &Frames);
@@ -215,10 +207,9 @@ struct YAMLCoffSymbolRVASubsection : public YAMLSubsectionBase {
: YAMLSubsectionBase(DebugSubsectionKind::CoffSymbolRVA) {}
void map(IO &IO) override;
- std::unique_ptr<DebugSubsection>
+ std::shared_ptr<DebugSubsection>
toCodeViewSubsection(BumpPtrAllocator &Allocator,
- DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const override;
+ const codeview::StringsAndChecksums &SC) const override;
static Expected<std::shared_ptr<YAMLCoffSymbolRVASubsection>>
fromCodeViewSubsection(const DebugSymbolRVASubsectionRef &RVAs);
@@ -389,34 +380,23 @@ void MappingTraits<YAMLDebugSubsection>::mapping(
Subsection.Subsection->map(IO);
}
-static std::shared_ptr<YAMLChecksumsSubsection>
-findChecksums(ArrayRef<YAMLDebugSubsection> Subsections) {
- for (const auto &SS : Subsections) {
- if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums) {
- return std::static_pointer_cast<YAMLChecksumsSubsection>(SS.Subsection);
- }
- }
-
- return nullptr;
-}
-
-std::unique_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
- DebugChecksumsSubsection *UseChecksums) const {
- assert(UseStrings && !UseChecksums);
- auto Result = llvm::make_unique<DebugChecksumsSubsection>(*UseStrings);
+std::shared_ptr<DebugSubsection> YAMLChecksumsSubsection::toCodeViewSubsection(
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ assert(SC.hasStrings());
+ auto Result = std::make_shared<DebugChecksumsSubsection>(*SC.strings());
for (const auto &CS : Checksums) {
Result->addChecksum(CS.FileName, CS.Kind, CS.ChecksumBytes.Bytes);
}
- return std::move(Result);
+ return Result;
}
-std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
- DebugChecksumsSubsection *UseChecksums) const {
- assert(UseStrings && UseChecksums);
+std::shared_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ assert(SC.hasStrings() && SC.hasChecksums());
auto Result =
- llvm::make_unique<DebugLinesSubsection>(*UseChecksums, *UseStrings);
+ std::make_shared<DebugLinesSubsection>(*SC.checksums(), *SC.strings());
Result->setCodeSize(Lines.CodeSize);
Result->setRelocationAddress(Lines.RelocSegment, Lines.RelocOffset);
Result->setFlags(Lines.Flags);
@@ -438,16 +418,16 @@ std::unique_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection(
}
}
}
- return llvm::cast<DebugSubsection>(std::move(Result));
+ return Result;
}
-std::unique_ptr<DebugSubsection>
+std::shared_ptr<DebugSubsection>
YAMLInlineeLinesSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *UseStrings,
- DebugChecksumsSubsection *UseChecksums) const {
- assert(UseChecksums);
- auto Result = llvm::make_unique<DebugInlineeLinesSubsection>(
- *UseChecksums, InlineeLines.HasExtraFiles);
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ assert(SC.hasChecksums());
+ auto Result = std::make_shared<DebugInlineeLinesSubsection>(
+ *SC.checksums(), InlineeLines.HasExtraFiles);
for (const auto &Site : InlineeLines.Sites) {
Result->addInlineSite(TypeIndex(Site.Inlinee), Site.FileName,
@@ -459,56 +439,60 @@ YAMLInlineeLinesSubsection::toCodeViewSubsection(
Result->addExtraFile(EF);
}
}
- return llvm::cast<DebugSubsection>(std::move(Result));
+ return Result;
}
-std::unique_ptr<DebugSubsection>
+std::shared_ptr<DebugSubsection>
YAMLCrossModuleExportsSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const {
- auto Result = llvm::make_unique<DebugCrossModuleExportsSubsection>();
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ auto Result = std::make_shared<DebugCrossModuleExportsSubsection>();
for (const auto &M : Exports)
Result->addMapping(M.Local, M.Global);
- return llvm::cast<DebugSubsection>(std::move(Result));
+ return Result;
}
-std::unique_ptr<DebugSubsection>
+std::shared_ptr<DebugSubsection>
YAMLCrossModuleImportsSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const {
- auto Result = llvm::make_unique<DebugCrossModuleImportsSubsection>(*Strings);
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ assert(SC.hasStrings());
+
+ auto Result =
+ std::make_shared<DebugCrossModuleImportsSubsection>(*SC.strings());
for (const auto &M : Imports) {
for (const auto Id : M.ImportIds)
Result->addImport(M.ModuleName, Id);
}
- return llvm::cast<DebugSubsection>(std::move(Result));
+ return Result;
}
-std::unique_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const {
- auto Result = llvm::make_unique<DebugSymbolsSubsection>();
+std::shared_ptr<DebugSubsection> YAMLSymbolsSubsection::toCodeViewSubsection(
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ auto Result = std::make_shared<DebugSymbolsSubsection>();
for (const auto &Sym : Symbols)
Result->addSymbol(
Sym.toCodeViewSymbol(Allocator, CodeViewContainer::ObjectFile));
- return std::move(Result);
+ return Result;
}
-std::unique_ptr<DebugSubsection>
+std::shared_ptr<DebugSubsection>
YAMLStringTableSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const {
- auto Result = llvm::make_unique<DebugStringTableSubsection>();
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ auto Result = std::make_shared<DebugStringTableSubsection>();
for (const auto &Str : this->Strings)
Result->insert(Str);
- return std::move(Result);
+ return Result;
}
-std::unique_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const {
- assert(Strings);
- auto Result = llvm::make_unique<DebugFrameDataSubsection>();
+std::shared_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ assert(SC.hasStrings());
+
+ auto Result = std::make_shared<DebugFrameDataSubsection>();
for (const auto &YF : Frames) {
codeview::FrameData F;
F.CodeSize = YF.CodeSize;
@@ -519,20 +503,20 @@ std::unique_ptr<DebugSubsection> YAMLFrameDataSubsection::toCodeViewSubsection(
F.PrologSize = YF.PrologSize;
F.RvaStart = YF.RvaStart;
F.SavedRegsSize = YF.SavedRegsSize;
- F.FrameFunc = Strings->insert(YF.FrameFunc);
+ F.FrameFunc = SC.strings()->insert(YF.FrameFunc);
Result->addFrameData(F);
}
- return std::move(Result);
+ return Result;
}
-std::unique_ptr<DebugSubsection>
+std::shared_ptr<DebugSubsection>
YAMLCoffSymbolRVASubsection::toCodeViewSubsection(
- BumpPtrAllocator &Allocator, DebugStringTableSubsection *Strings,
- DebugChecksumsSubsection *Checksums) const {
- auto Result = llvm::make_unique<DebugSymbolRVASubsection>();
+ BumpPtrAllocator &Allocator,
+ const codeview::StringsAndChecksums &SC) const {
+ auto Result = std::make_shared<DebugSymbolRVASubsection>();
for (const auto &RVA : RVAs)
Result->addRVA(RVA);
- return std::move(Result);
+ return Result;
}
static Expected<SourceFileChecksumEntry>
@@ -741,63 +725,17 @@ YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(
return Result;
}
-Expected<std::vector<std::unique_ptr<DebugSubsection>>>
+Expected<std::vector<std::shared_ptr<DebugSubsection>>>
llvm::CodeViewYAML::toCodeViewSubsectionList(
BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
- DebugStringTableSubsection &Strings) {
- std::vector<std::unique_ptr<DebugSubsection>> Result;
+ const codeview::StringsAndChecksums &SC) {
+ std::vector<std::shared_ptr<DebugSubsection>> Result;
if (Subsections.empty())
return std::move(Result);
- auto Checksums = findChecksums(Subsections);
- std::unique_ptr<DebugSubsection> ChecksumsBase;
- if (Checksums)
- ChecksumsBase =
- Checksums->toCodeViewSubsection(Allocator, &Strings, nullptr);
- DebugChecksumsSubsection *CS =
- static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
for (const auto &SS : Subsections) {
- // We've already converted the checksums subsection, don't do it
- // twice.
- std::unique_ptr<DebugSubsection> CVS;
- if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
- CVS = std::move(ChecksumsBase);
- else
- CVS = SS.Subsection->toCodeViewSubsection(Allocator, &Strings, CS);
- assert(CVS != nullptr);
- Result.push_back(std::move(CVS));
- }
- return std::move(Result);
-}
-
-Expected<std::vector<std::unique_ptr<codeview::DebugSubsection>>>
-llvm::CodeViewYAML::toCodeViewSubsectionList(
- BumpPtrAllocator &Allocator, ArrayRef<YAMLDebugSubsection> Subsections,
- std::unique_ptr<DebugStringTableSubsection> &TakeStrings,
- DebugStringTableSubsection *StringsRef) {
- std::vector<std::unique_ptr<DebugSubsection>> Result;
- if (Subsections.empty())
- return std::move(Result);
-
- auto Checksums = findChecksums(Subsections);
-
- std::unique_ptr<DebugSubsection> ChecksumsBase;
- if (Checksums)
- ChecksumsBase =
- Checksums->toCodeViewSubsection(Allocator, StringsRef, nullptr);
- DebugChecksumsSubsection *CS =
- static_cast<DebugChecksumsSubsection *>(ChecksumsBase.get());
- for (const auto &SS : Subsections) {
- // We've already converted the checksums and string table subsection, don't
- // do it twice.
- std::unique_ptr<DebugSubsection> CVS;
- if (SS.Subsection->Kind == DebugSubsectionKind::FileChecksums)
- CVS = std::move(ChecksumsBase);
- else if (SS.Subsection->Kind == DebugSubsectionKind::StringTable) {
- assert(TakeStrings && "No string table!");
- CVS = std::move(TakeStrings);
- } else
- CVS = SS.Subsection->toCodeViewSubsection(Allocator, StringsRef, CS);
+ std::shared_ptr<DebugSubsection> CVS;
+ CVS = SS.Subsection->toCodeViewSubsection(Allocator, SC);
assert(CVS != nullptr);
Result.push_back(std::move(CVS));
}
@@ -810,23 +748,23 @@ struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
Error visitLines(DebugLinesSubsectionRef &Lines,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitStringTable(DebugStringTableSubsectionRef &ST,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitFrameData(DebugFrameDataSubsectionRef &Symbols,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &Symbols,
- const DebugSubsectionState &State) override;
+ const StringsAndChecksumsRef &State) override;
YAMLDebugSubsection Subsection;
};
@@ -837,7 +775,7 @@ Error SubsectionConversionVisitor::visitUnknown(
}
Error SubsectionConversionVisitor::visitLines(
- DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) {
+ DebugLinesSubsectionRef &Lines, const StringsAndChecksumsRef &State) {
auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
State.strings(), State.checksums(), Lines);
if (!Result)
@@ -847,7 +785,8 @@ Error SubsectionConversionVisitor::visitLines(
}
Error SubsectionConversionVisitor::visitFileChecksums(
- DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) {
+ DebugChecksumsSubsectionRef &Checksums,
+ const StringsAndChecksumsRef &State) {
auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
Checksums);
if (!Result)
@@ -858,7 +797,7 @@ Error SubsectionConversionVisitor::visitFileChecksums(
Error SubsectionConversionVisitor::visitInlineeLines(
DebugInlineeLinesSubsectionRef &Inlinees,
- const DebugSubsectionState &State) {
+ const StringsAndChecksumsRef &State) {
auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
State.strings(), State.checksums(), Inlinees);
if (!Result)
@@ -869,7 +808,7 @@ Error SubsectionConversionVisitor::visitInlineeLines(
Error SubsectionConversionVisitor::visitCrossModuleExports(
DebugCrossModuleExportsSubsectionRef &Exports,
- const DebugSubsectionState &State) {
+ const StringsAndChecksumsRef &State) {
auto Result =
YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
if (!Result)
@@ -880,7 +819,7 @@ Error SubsectionConversionVisitor::visitCrossModuleExports(
Error SubsectionConversionVisitor::visitCrossModuleImports(
DebugCrossModuleImportsSubsectionRef &Imports,
- const DebugSubsectionState &State) {
+ const StringsAndChecksumsRef &State) {
auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
State.strings(), Imports);
if (!Result)
@@ -890,7 +829,8 @@ Error SubsectionConversionVisitor::visitCrossModuleImports(
}
Error SubsectionConversionVisitor::visitStringTable(
- DebugStringTableSubsectionRef &Strings, const DebugSubsectionState &State) {
+ DebugStringTableSubsectionRef &Strings,
+ const StringsAndChecksumsRef &State) {
auto Result = YAMLStringTableSubsection::fromCodeViewSubsection(Strings);
if (!Result)
return Result.takeError();
@@ -899,7 +839,7 @@ Error SubsectionConversionVisitor::visitStringTable(
}
Error SubsectionConversionVisitor::visitSymbols(
- DebugSymbolsSubsectionRef &Symbols, const DebugSubsectionState &State) {
+ DebugSymbolsSubsectionRef &Symbols, const StringsAndChecksumsRef &State) {
auto Result = YAMLSymbolsSubsection::fromCodeViewSubsection(Symbols);
if (!Result)
return Result.takeError();
@@ -908,7 +848,7 @@ Error SubsectionConversionVisitor::visitSymbols(
}
Error SubsectionConversionVisitor::visitFrameData(
- DebugFrameDataSubsectionRef &Frames, const DebugSubsectionState &State) {
+ DebugFrameDataSubsectionRef &Frames, const StringsAndChecksumsRef &State) {
auto Result =
YAMLFrameDataSubsection::fromCodeViewSubsection(State.strings(), Frames);
if (!Result)
@@ -918,7 +858,7 @@ Error SubsectionConversionVisitor::visitFrameData(
}
Error SubsectionConversionVisitor::visitCOFFSymbolRVAs(
- DebugSymbolRVASubsectionRef &RVAs, const DebugSubsectionState &State) {
+ DebugSymbolRVASubsectionRef &RVAs, const StringsAndChecksumsRef &State) {
auto Result = YAMLCoffSymbolRVASubsection::fromCodeViewSubsection(RVAs);
if (!Result)
return Result.takeError();
@@ -927,29 +867,71 @@ Error SubsectionConversionVisitor::visitCOFFSymbolRVAs(
}
}
-Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
- const DebugStringTableSubsectionRef &Strings,
- const DebugChecksumsSubsectionRef &Checksums,
- const DebugSubsectionRecord &SS) {
- DebugSubsectionState State(Strings, Checksums);
+Expected<YAMLDebugSubsection>
+YAMLDebugSubsection::fromCodeViewSubection(const StringsAndChecksumsRef &SC,
+ const DebugSubsectionRecord &SS) {
SubsectionConversionVisitor V;
- if (auto EC = visitDebugSubsection(SS, V, State))
+ if (auto EC = visitDebugSubsection(SS, V, SC))
return std::move(EC);
return V.Subsection;
}
-std::unique_ptr<DebugStringTableSubsection>
-llvm::CodeViewYAML::findStringTable(ArrayRef<YAMLDebugSubsection> Sections) {
- for (const auto &SS : Sections) {
- if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
- continue;
+std::vector<YAMLDebugSubsection>
+llvm::CodeViewYAML::fromDebugS(ArrayRef<uint8_t> Data,
+ const StringsAndChecksumsRef &SC) {
+ BinaryStreamReader Reader(Data, support::little);
+ uint32_t Magic;
+
+ ExitOnError Err("Invalid .debug$S section!");
+ Err(Reader.readInteger(Magic));
+ assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
+
+ DebugSubsectionArray Subsections;
+ Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
+
+ std::vector<YAMLDebugSubsection> Result;
- // String Table doesn't use the allocator.
- BumpPtrAllocator Allocator;
- auto Result =
- SS.Subsection->toCodeViewSubsection(Allocator, nullptr, nullptr);
- return llvm::cast<DebugStringTableSubsection>(std::move(Result));
+ for (const auto &SS : Subsections) {
+ auto YamlSS = Err(YAMLDebugSubsection::fromCodeViewSubection(SC, SS));
+ Result.push_back(YamlSS);
+ }
+ return Result;
+}
+
+void llvm::CodeViewYAML::initializeStringsAndChecksums(
+ ArrayRef<YAMLDebugSubsection> Sections, codeview::StringsAndChecksums &SC) {
+ // String Table and Checksums subsections don't use the allocator.
+ BumpPtrAllocator Allocator;
+
+ // It's possible for checksums and strings to even appear in different debug$S
+ // sections, so we have to make this a stateful function that can build up
+ // the strings and checksums field over multiple iterations.
+
+ // File Checksums require the string table, but may become before it, so we
+ // have to scan for strings first, then scan for checksums again from the
+ // beginning.
+ if (!SC.hasStrings()) {
+ for (const auto &SS : Sections) {
+ if (SS.Subsection->Kind != DebugSubsectionKind::StringTable)
+ continue;
+
+ auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
+ SC.setStrings(
+ std::static_pointer_cast<DebugStringTableSubsection>(Result));
+ break;
+ }
+ }
+
+ if (SC.hasStrings() && !SC.hasChecksums()) {
+ for (const auto &SS : Sections) {
+ if (SS.Subsection->Kind != DebugSubsectionKind::FileChecksums)
+ continue;
+
+ auto Result = SS.Subsection->toCodeViewSubsection(Allocator, SC);
+ SC.setChecksums(
+ std::static_pointer_cast<DebugChecksumsSubsection>(Result));
+ break;
+ }
}
- return nullptr;
}
diff --git a/lib/ObjectYAML/CodeViewYAMLSymbols.cpp b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
index fa3f1e0b60aa..ba3a2abe2097 100644
--- a/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
+++ b/lib/ObjectYAML/CodeViewYAMLSymbols.cpp
@@ -35,6 +35,7 @@ LLVM_YAML_DECLARE_SCALAR_TRAITS(APSInt, false)
LLVM_YAML_DECLARE_SCALAR_TRAITS(TypeIndex, false)
LLVM_YAML_DECLARE_ENUM_TRAITS(SymbolKind)
+LLVM_YAML_DECLARE_ENUM_TRAITS(FrameCookieKind)
LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym2Flags)
LLVM_YAML_DECLARE_BITSET_TRAITS(CompileSym3Flags)
@@ -149,6 +150,15 @@ void ScalarEnumerationTraits<ThunkOrdinal>::enumeration(IO &io,
}
}
+void ScalarEnumerationTraits<FrameCookieKind>::enumeration(
+ IO &io, FrameCookieKind &FC) {
+ auto ThunkNames = getFrameCookieKindNames();
+ for (const auto &E : ThunkNames) {
+ io.enumCase(FC, E.Name.str().c_str(),
+ static_cast<FrameCookieKind>(E.Value));
+ }
+}
+
namespace llvm {
namespace CodeViewYAML {
namespace detail {
@@ -183,8 +193,47 @@ template <typename T> struct SymbolRecordImpl : public SymbolRecordBase {
mutable T Symbol;
};
+struct UnknownSymbolRecord : public SymbolRecordBase {
+ explicit UnknownSymbolRecord(codeview::SymbolKind K) : SymbolRecordBase(K) {}
+
+ void map(yaml::IO &io) override;
+
+ CVSymbol toCodeViewSymbol(BumpPtrAllocator &Allocator,
+ CodeViewContainer Container) const override {
+ RecordPrefix Prefix;
+ uint32_t TotalLen = sizeof(RecordPrefix) + Data.size();
+ Prefix.RecordKind = Kind;
+ Prefix.RecordLen = TotalLen - 2;
+ uint8_t *Buffer = Allocator.Allocate<uint8_t>(TotalLen);
+ ::memcpy(Buffer, &Prefix, sizeof(RecordPrefix));
+ ::memcpy(Buffer + sizeof(RecordPrefix), Data.data(), Data.size());
+ return CVSymbol(Kind, ArrayRef<uint8_t>(Buffer, TotalLen));
+ }
+ Error fromCodeViewSymbol(CVSymbol CVS) override {
+ this->Kind = CVS.kind();
+ Data = CVS.RecordData.drop_front(sizeof(RecordPrefix));
+ return Error::success();
+ }
+
+ std::vector<uint8_t> Data;
+};
+
template <> void SymbolRecordImpl<ScopeEndSym>::map(IO &IO) {}
+void UnknownSymbolRecord::map(yaml::IO &io) {
+ yaml::BinaryRef Binary;
+ if (io.outputting())
+ Binary = yaml::BinaryRef(Data);
+ io.mapRequired("Data", Binary);
+ if (!io.outputting()) {
+ std::string Str;
+ raw_string_ostream OS(Str);
+ Binary.writeAsBinary(OS);
+ OS.flush();
+ Data.assign(Str.begin(), Str.end());
+ }
+}
+
template <> void SymbolRecordImpl<Thunk32Sym>::map(IO &IO) {
IO.mapRequired("Parent", Symbol.Parent);
IO.mapRequired("End", Symbol.End);
@@ -461,7 +510,7 @@ static inline Expected<CodeViewYAML::SymbolRecord>
fromCodeViewSymbolImpl(CVSymbol Symbol) {
CodeViewYAML::SymbolRecord Result;
- auto Impl = std::make_shared<SymbolRecordImpl<SymbolType>>(Symbol.kind());
+ auto Impl = std::make_shared<SymbolType>(Symbol.kind());
if (auto EC = Impl->fromCodeViewSymbol(Symbol))
return std::move(EC);
Result.Symbol = Impl;
@@ -472,12 +521,13 @@ Expected<CodeViewYAML::SymbolRecord>
CodeViewYAML::SymbolRecord::fromCodeViewSymbol(CVSymbol Symbol) {
#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
case EnumName: \
- return fromCodeViewSymbolImpl<ClassName>(Symbol);
+ return fromCodeViewSymbolImpl<SymbolRecordImpl<ClassName>>(Symbol);
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
SYMBOL_RECORD(EnumName, EnumVal, ClassName)
switch (Symbol.kind()) {
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
- default: { llvm_unreachable("Unknown symbol kind!"); }
+ default:
+ return fromCodeViewSymbolImpl<UnknownSymbolRecord>(Symbol);
}
return make_error<CodeViewError>(cv_error_code::corrupt_record);
}
@@ -486,7 +536,7 @@ template <typename ConcreteType>
static void mapSymbolRecordImpl(IO &IO, const char *Class, SymbolKind Kind,
CodeViewYAML::SymbolRecord &Obj) {
if (!IO.outputting())
- Obj.Symbol = std::make_shared<SymbolRecordImpl<ConcreteType>>(Kind);
+ Obj.Symbol = std::make_shared<ConcreteType>(Kind);
IO.mapRequired(Class, *Obj.Symbol);
}
@@ -500,12 +550,14 @@ void MappingTraits<CodeViewYAML::SymbolRecord>::mapping(
#define SYMBOL_RECORD(EnumName, EnumVal, ClassName) \
case EnumName: \
- mapSymbolRecordImpl<ClassName>(IO, #ClassName, Kind, Obj); \
+ mapSymbolRecordImpl<SymbolRecordImpl<ClassName>>(IO, #ClassName, Kind, \
+ Obj); \
break;
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, AliasName, ClassName) \
SYMBOL_RECORD(EnumName, EnumVal, ClassName)
switch (Kind) {
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
- default: { llvm_unreachable("Unknown symbol kind!"); }
+ default:
+ mapSymbolRecordImpl<UnknownSymbolRecord>(IO, "UnknownSym", Kind, Obj);
}
}
diff --git a/lib/ObjectYAML/CodeViewYAMLTypes.cpp b/lib/ObjectYAML/CodeViewYAMLTypes.cpp
index 1302b0713d0e..a03b9cd50faa 100644
--- a/lib/ObjectYAML/CodeViewYAMLTypes.cpp
+++ b/lib/ObjectYAML/CodeViewYAMLTypes.cpp
@@ -714,3 +714,43 @@ void MappingTraits<MemberRecord>::mapping(IO &IO, MemberRecord &Obj) {
default: { llvm_unreachable("Unknown member kind!"); }
}
}
+
+std::vector<LeafRecord>
+llvm::CodeViewYAML::fromDebugT(ArrayRef<uint8_t> DebugT) {
+ ExitOnError Err("Invalid .debug$T section!");
+ BinaryStreamReader Reader(DebugT, support::little);
+ CVTypeArray Types;
+ uint32_t Magic;
+
+ Err(Reader.readInteger(Magic));
+ assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$T section!");
+
+ std::vector<LeafRecord> Result;
+ Err(Reader.readArray(Types, Reader.bytesRemaining()));
+ for (const auto &T : Types) {
+ auto CVT = Err(LeafRecord::fromCodeViewRecord(T));
+ Result.push_back(CVT);
+ }
+ return Result;
+}
+
+ArrayRef<uint8_t> llvm::CodeViewYAML::toDebugT(ArrayRef<LeafRecord> Leafs,
+ BumpPtrAllocator &Alloc) {
+ TypeTableBuilder TTB(Alloc, false);
+ uint32_t Size = sizeof(uint32_t);
+ for (const auto &Leaf : Leafs) {
+ CVType T = Leaf.toCodeViewRecord(TTB);
+ Size += T.length();
+ assert(T.length() % 4 == 0 && "Improper type record alignment!");
+ }
+ uint8_t *ResultBuffer = Alloc.Allocate<uint8_t>(Size);
+ MutableArrayRef<uint8_t> Output(ResultBuffer, Size);
+ BinaryStreamWriter Writer(Output, support::little);
+ ExitOnError Err("Error writing type record to .debug$T section");
+ Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC));
+ for (const auto &R : TTB.records()) {
+ Err(Writer.writeBytes(R));
+ }
+ assert(Writer.bytesRemaining() == 0 && "Didn't write all type record bytes!");
+ return Output;
+}
diff --git a/lib/ObjectYAML/ELFYAML.cpp b/lib/ObjectYAML/ELFYAML.cpp
index 70e25ea504a0..dbd5498e003d 100644
--- a/lib/ObjectYAML/ELFYAML.cpp
+++ b/lib/ObjectYAML/ELFYAML.cpp
@@ -372,6 +372,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_SHT>::enumeration(
ECase(SHT_GROUP);
ECase(SHT_SYMTAB_SHNDX);
ECase(SHT_LOOS);
+ ECase(SHT_LLVM_ODRTAB);
ECase(SHT_GNU_ATTRIBUTES);
ECase(SHT_GNU_HASH);
ECase(SHT_GNU_verdef);
diff --git a/lib/Option/Arg.cpp b/lib/Option/Arg.cpp
index e416df6a38dc..e581fee8bf38 100644
--- a/lib/Option/Arg.cpp
+++ b/lib/Option/Arg.cpp
@@ -1,4 +1,4 @@
-//===--- Arg.cpp - Argument Implementations -------------------------------===//
+//===- Arg.cpp - Argument Implementations ---------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,11 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Option/Arg.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Twine.h"
+#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -67,7 +67,7 @@ LLVM_DUMP_METHOD void Arg::dump() const { print(dbgs()); }
std::string Arg::getAsString(const ArgList &Args) const {
SmallString<256> Res;
- llvm::raw_svector_ostream OS(Res);
+ raw_svector_ostream OS(Res);
ArgStringList ASL;
render(Args, ASL);
@@ -98,7 +98,7 @@ void Arg::render(const ArgList &Args, ArgStringList &Output) const {
case Option::RenderCommaJoinedStyle: {
SmallString<256> Res;
- llvm::raw_svector_ostream OS(Res);
+ raw_svector_ostream OS(Res);
OS << getSpelling();
for (unsigned i = 0, e = getNumValues(); i != e; ++i) {
if (i) OS << ',';
diff --git a/lib/Option/ArgList.cpp b/lib/Option/ArgList.cpp
index 39dbce87f9ae..cbccc1935d3c 100644
--- a/lib/Option/ArgList.cpp
+++ b/lib/Option/ArgList.cpp
@@ -1,4 +1,4 @@
-//===--- ArgList.cpp - Argument List Management ---------------------------===//
+//===- ArgList.cpp - Argument List Management -----------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,14 +7,25 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Option/ArgList.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
+#include "llvm/Option/OptSpecifier.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
using namespace llvm;
using namespace llvm::opt;
@@ -197,8 +208,6 @@ void ArgList::print(raw_ostream &O) const {
LLVM_DUMP_METHOD void ArgList::dump() const { print(dbgs()); }
#endif
-//
-
void InputArgList::releaseMemory() {
// An InputArgList always owns its arguments.
for (Arg *A : *this)
@@ -234,8 +243,6 @@ const char *InputArgList::MakeArgStringRef(StringRef Str) const {
return getArgString(MakeIndex(Str));
}
-//
-
DerivedArgList::DerivedArgList(const InputArgList &BaseArgs)
: BaseArgs(BaseArgs) {}
diff --git a/lib/Option/OptTable.cpp b/lib/Option/OptTable.cpp
index b00d21ec8f67..52a81ff0e159 100644
--- a/lib/Option/OptTable.cpp
+++ b/lib/Option/OptTable.cpp
@@ -1,4 +1,4 @@
-//===--- OptTable.cpp - Option Table Implementation -----------------------===//
+//===- OptTable.cpp - Option Table Implementation -------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,16 +7,25 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Option/OptTable.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
+#include "llvm/Option/OptSpecifier.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
+#include <cassert>
#include <cctype>
+#include <cstring>
#include <map>
+#include <string>
+#include <utility>
+#include <vector>
using namespace llvm;
using namespace llvm::opt;
@@ -80,14 +89,14 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
static inline bool operator<(const OptTable::Info &I, const char *Name) {
return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
}
-}
-}
+
+} // end namespace opt
+} // end namespace llvm
OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
- : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase), TheInputOptionID(0),
- TheUnknownOptionID(0), FirstSearchableIndex(0) {
+ : OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) {
// Explicitly zero initialize the error to work around a bug in array
// value-initialization on MinGW with gcc 4.3.5.
@@ -138,8 +147,8 @@ OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
}
// Build prefix chars.
- for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(),
- E = PrefixesUnion.end(); I != E; ++I) {
+ for (StringSet<>::const_iterator I = PrefixesUnion.begin(),
+ E = PrefixesUnion.end(); I != E; ++I) {
StringRef Prefix = I->getKey();
for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
C != CE; ++C)
@@ -148,8 +157,7 @@ OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
}
}
-OptTable::~OptTable() {
-}
+OptTable::~OptTable() = default;
const Option OptTable::getOption(OptSpecifier Opt) const {
unsigned id = Opt.getID();
@@ -159,11 +167,11 @@ const Option OptTable::getOption(OptSpecifier Opt) const {
return Option(&getInfo(id), this);
}
-static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) {
+static bool isInput(const StringSet<> &Prefixes, StringRef Arg) {
if (Arg == "-")
return true;
- for (llvm::StringSet<>::const_iterator I = Prefixes.begin(),
- E = Prefixes.end(); I != E; ++I)
+ for (StringSet<>::const_iterator I = Prefixes.begin(),
+ E = Prefixes.end(); I != E; ++I)
if (Arg.startswith(I->getKey()))
return false;
return true;
@@ -346,7 +354,7 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
static void PrintHelpOptionList(raw_ostream &OS, StringRef Title,
std::vector<std::pair<std::string,
- const char*> > &OptionHelp) {
+ const char*>> &OptionHelp) {
OS << Title << ":\n";
// Find the maximum option length.
@@ -412,8 +420,8 @@ void OptTable::PrintHelp(raw_ostream &OS, const char *Name, const char *Title,
// Render help text into a map of group-name to a list of (option, help)
// pairs.
- typedef std::map<std::string,
- std::vector<std::pair<std::string, const char*> > > helpmap_ty;
+ using helpmap_ty =
+ std::map<std::string, std::vector<std::pair<std::string, const char*>>>;
helpmap_ty GroupedOptionHelp;
for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
diff --git a/lib/Option/Option.cpp b/lib/Option/Option.cpp
index 736b939fe80b..4832e659f026 100644
--- a/lib/Option/Option.cpp
+++ b/lib/Option/Option.cpp
@@ -1,4 +1,4 @@
-//===--- Option.cpp - Abstract Driver Options -----------------------------===//
+//===- Option.cpp - Abstract Driver Options -------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,22 +7,24 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Option/Option.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
#include <cassert>
+#include <cstring>
using namespace llvm;
using namespace llvm::opt;
Option::Option(const OptTable::Info *info, const OptTable *owner)
: Info(info), Owner(owner) {
-
// Multi-level aliases are not supported. This just simplifies option
// tracking, it is not an inherent limitation.
assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
diff --git a/lib/Passes/PassBuilder.cpp b/lib/Passes/PassBuilder.cpp
index 1f638e768307..afd66f55720a 100644
--- a/lib/Passes/PassBuilder.cpp
+++ b/lib/Passes/PassBuilder.cpp
@@ -160,6 +160,10 @@ static cl::opt<bool>
cl::Hidden, cl::ZeroOrMore,
cl::desc("Run NewGVN instead of GVN"));
+static cl::opt<bool> EnableEarlyCSEMemSSA(
+ "enable-npm-earlycse-memssa", cl::init(false), cl::Hidden,
+ cl::desc("Enable the EarlyCSE w/ MemorySSA pass for the new PM (default = off)"));
+
static cl::opt<bool> EnableGVNHoist(
"enable-npm-gvn-hoist", cl::init(false), cl::Hidden,
cl::desc("Enable the GVN hoisting pass for the new PM (default = off)"));
@@ -312,7 +316,7 @@ PassBuilder::buildFunctionSimplificationPipeline(OptimizationLevel Level,
FPM.addPass(SROA());
// Catch trivial redundancies
- FPM.addPass(EarlyCSEPass());
+ FPM.addPass(EarlyCSEPass(EnableEarlyCSEMemSSA));
// Hoisting of scalars and load expressions.
if (EnableGVNHoist)
diff --git a/lib/Support/BinaryStreamWriter.cpp b/lib/Support/BinaryStreamWriter.cpp
index b22eb1ed12d0..c4276518b191 100644
--- a/lib/Support/BinaryStreamWriter.cpp
+++ b/lib/Support/BinaryStreamWriter.cpp
@@ -83,6 +83,8 @@ Error BinaryStreamWriter::padToAlignment(uint32_t Align) {
uint32_t NewOffset = alignTo(Offset, Align);
if (NewOffset > getLength())
return make_error<BinaryStreamError>(stream_error_code::stream_too_short);
- Offset = NewOffset;
+ while (Offset < NewOffset)
+ if (auto EC = writeInteger('\0'))
+ return EC;
return Error::success();
}
diff --git a/lib/Support/DebugCounter.cpp b/lib/Support/DebugCounter.cpp
index a10ac8e85396..1d46de04ee6a 100644
--- a/lib/Support/DebugCounter.cpp
+++ b/lib/Support/DebugCounter.cpp
@@ -102,9 +102,13 @@ void DebugCounter::push_back(const std::string &Val) {
}
}
-void DebugCounter::print(raw_ostream &OS) {
+void DebugCounter::print(raw_ostream &OS) const {
OS << "Counters and values:\n";
for (const auto &KV : Counters)
OS << left_justify(RegisteredCounters[KV.first], 32) << ": {"
<< KV.second.first << "," << KV.second.second << "}\n";
}
+
+LLVM_DUMP_METHOD void DebugCounter::dump() const {
+ print(dbgs());
+}
diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp
index c9bca7f4c1ab..4496d06a15f3 100644
--- a/lib/Support/FoldingSet.cpp
+++ b/lib/Support/FoldingSet.cpp
@@ -26,7 +26,7 @@ using namespace llvm;
// FoldingSetNodeIDRef Implementation
/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
-/// used to lookup the node in the FoldingSetImpl.
+/// used to lookup the node in the FoldingSetBase.
unsigned FoldingSetNodeIDRef::ComputeHash() const {
return static_cast<unsigned>(hash_combine_range(Data, Data+Size));
}
@@ -142,7 +142,7 @@ void FoldingSetNodeID::AddNodeID(const FoldingSetNodeID &ID) {
}
/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used to
-/// lookup the node in the FoldingSetImpl.
+/// lookup the node in the FoldingSetBase.
unsigned FoldingSetNodeID::ComputeHash() const {
return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
}
@@ -180,7 +180,7 @@ FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const {
}
//===----------------------------------------------------------------------===//
-/// Helper functions for FoldingSetImpl.
+/// Helper functions for FoldingSetBase.
/// GetNextPtr - In order to save space, each bucket is a
/// singly-linked-list. In order to make deletion more efficient, we make
@@ -188,12 +188,12 @@ FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const {
/// The problem with this is that the start of the hash buckets are not
/// Nodes. If NextInBucketPtr is a bucket pointer, this method returns null:
/// use GetBucketPtr when this happens.
-static FoldingSetImpl::Node *GetNextPtr(void *NextInBucketPtr) {
+static FoldingSetBase::Node *GetNextPtr(void *NextInBucketPtr) {
// The low bit is set if this is the pointer back to the bucket.
if (reinterpret_cast<intptr_t>(NextInBucketPtr) & 1)
return nullptr;
- return static_cast<FoldingSetImpl::Node*>(NextInBucketPtr);
+ return static_cast<FoldingSetBase::Node*>(NextInBucketPtr);
}
@@ -221,11 +221,11 @@ static void **AllocateBuckets(unsigned NumBuckets) {
}
//===----------------------------------------------------------------------===//
-// FoldingSetImpl Implementation
+// FoldingSetBase Implementation
-void FoldingSetImpl::anchor() {}
+void FoldingSetBase::anchor() {}
-FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) {
+FoldingSetBase::FoldingSetBase(unsigned Log2InitSize) {
assert(5 < Log2InitSize && Log2InitSize < 32 &&
"Initial hash table size out of range");
NumBuckets = 1 << Log2InitSize;
@@ -233,14 +233,14 @@ FoldingSetImpl::FoldingSetImpl(unsigned Log2InitSize) {
NumNodes = 0;
}
-FoldingSetImpl::FoldingSetImpl(FoldingSetImpl &&Arg)
+FoldingSetBase::FoldingSetBase(FoldingSetBase &&Arg)
: Buckets(Arg.Buckets), NumBuckets(Arg.NumBuckets), NumNodes(Arg.NumNodes) {
Arg.Buckets = nullptr;
Arg.NumBuckets = 0;
Arg.NumNodes = 0;
}
-FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) {
+FoldingSetBase &FoldingSetBase::operator=(FoldingSetBase &&RHS) {
free(Buckets); // This may be null if the set is in a moved-from state.
Buckets = RHS.Buckets;
NumBuckets = RHS.NumBuckets;
@@ -251,11 +251,11 @@ FoldingSetImpl &FoldingSetImpl::operator=(FoldingSetImpl &&RHS) {
return *this;
}
-FoldingSetImpl::~FoldingSetImpl() {
+FoldingSetBase::~FoldingSetBase() {
free(Buckets);
}
-void FoldingSetImpl::clear() {
+void FoldingSetBase::clear() {
// Set all but the last bucket to null pointers.
memset(Buckets, 0, NumBuckets*sizeof(void*));
@@ -266,7 +266,7 @@ void FoldingSetImpl::clear() {
NumNodes = 0;
}
-void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) {
+void FoldingSetBase::GrowBucketCount(unsigned NewBucketCount) {
assert((NewBucketCount > NumBuckets) && "Can't shrink a folding set with GrowBucketCount");
assert(isPowerOf2_32(NewBucketCount) && "Bad bucket count!");
void **OldBuckets = Buckets;
@@ -300,11 +300,11 @@ void FoldingSetImpl::GrowBucketCount(unsigned NewBucketCount) {
/// GrowHashTable - Double the size of the hash table and rehash everything.
///
-void FoldingSetImpl::GrowHashTable() {
+void FoldingSetBase::GrowHashTable() {
GrowBucketCount(NumBuckets * 2);
}
-void FoldingSetImpl::reserve(unsigned EltCount) {
+void FoldingSetBase::reserve(unsigned EltCount) {
// This will give us somewhere between EltCount / 2 and
// EltCount buckets. This puts us in the load factor
// range of 1.0 - 2.0.
@@ -316,9 +316,9 @@ void FoldingSetImpl::reserve(unsigned EltCount) {
/// FindNodeOrInsertPos - Look up the node specified by ID. If it exists,
/// return it. If not, return the insertion token that will make insertion
/// faster.
-FoldingSetImpl::Node
-*FoldingSetImpl::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
- void *&InsertPos) {
+FoldingSetBase::Node *
+FoldingSetBase::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
+ void *&InsertPos) {
unsigned IDHash = ID.ComputeHash();
void **Bucket = GetBucketFor(IDHash, Buckets, NumBuckets);
void *Probe = *Bucket;
@@ -342,7 +342,7 @@ FoldingSetImpl::Node
/// InsertNode - Insert the specified node into the folding set, knowing that it
/// is not already in the map. InsertPos must be obtained from
/// FindNodeOrInsertPos.
-void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
+void FoldingSetBase::InsertNode(Node *N, void *InsertPos) {
assert(!N->getNextInBucket());
// Do we need to grow the hashtable?
if (NumNodes+1 > capacity()) {
@@ -371,7 +371,7 @@ void FoldingSetImpl::InsertNode(Node *N, void *InsertPos) {
/// RemoveNode - Remove a node from the folding set, returning true if one was
/// removed or false if the node was not in the folding set.
-bool FoldingSetImpl::RemoveNode(Node *N) {
+bool FoldingSetBase::RemoveNode(Node *N) {
// Because each bucket is a circular list, we don't need to compute N's hash
// to remove it.
void *Ptr = N->getNextInBucket();
@@ -412,7 +412,7 @@ bool FoldingSetImpl::RemoveNode(Node *N) {
/// GetOrInsertNode - If there is an existing simple Node exactly
/// equal to the specified node, return it. Otherwise, insert 'N' and it
/// instead.
-FoldingSetImpl::Node *FoldingSetImpl::GetOrInsertNode(FoldingSetImpl::Node *N) {
+FoldingSetBase::Node *FoldingSetBase::GetOrInsertNode(FoldingSetBase::Node *N) {
FoldingSetNodeID ID;
GetNodeProfile(N, ID);
void *IP;
diff --git a/lib/Support/ThreadPool.cpp b/lib/Support/ThreadPool.cpp
index db03a4d6240d..22b7550d4971 100644
--- a/lib/Support/ThreadPool.cpp
+++ b/lib/Support/ThreadPool.cpp
@@ -53,11 +53,7 @@ ThreadPool::ThreadPool(unsigned ThreadCount)
Tasks.pop();
}
// Run the task we just grabbed
-#ifndef _MSC_VER
Task();
-#else
- Task(/* unused */ false);
-#endif
{
// Adjust `ActiveThreads`, in case someone waits on ThreadPool::wait()
@@ -82,7 +78,7 @@ void ThreadPool::wait() {
[&] { return !ActiveThreads && Tasks.empty(); });
}
-std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
+std::shared_future<void> ThreadPool::asyncImpl(TaskTy Task) {
/// Wrap the Task in a packaged_task to return a future object.
PackagedTaskTy PackagedTask(std::move(Task));
auto Future = PackagedTask.get_future();
@@ -128,25 +124,16 @@ void ThreadPool::wait() {
while (!Tasks.empty()) {
auto Task = std::move(Tasks.front());
Tasks.pop();
-#ifndef _MSC_VER
- Task();
-#else
- Task(/* unused */ false);
-#endif
+ Task();
}
}
-std::shared_future<ThreadPool::VoidTy> ThreadPool::asyncImpl(TaskTy Task) {
-#ifndef _MSC_VER
+std::shared_future<void> ThreadPool::asyncImpl(TaskTy Task) {
// Get a Future with launch::deferred execution using std::async
auto Future = std::async(std::launch::deferred, std::move(Task)).share();
// Wrap the future so that both ThreadPool::wait() can operate and the
// returned future can be sync'ed on.
PackagedTaskTy PackagedTask([Future]() { Future.get(); });
-#else
- auto Future = std::async(std::launch::deferred, std::move(Task), false).share();
- PackagedTaskTy PackagedTask([Future](bool) -> bool { Future.get(); return false; });
-#endif
Tasks.push(std::move(PackagedTask));
return Future;
}
diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc
index 7d3537e20727..2df0eaff47e5 100644
--- a/lib/Support/Unix/Program.inc
+++ b/lib/Support/Unix/Program.inc
@@ -163,16 +163,6 @@ static void SetMemoryLimits (unsigned size)
r.rlim_cur = limit;
setrlimit (RLIMIT_RSS, &r);
#endif
-#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it.
- // Don't set virtual memory limit if built with any Sanitizer. They need 80Tb
- // of virtual memory for shadow memory mapping.
-#if !LLVM_MEMORY_SANITIZER_BUILD && !LLVM_ADDRESS_SANITIZER_BUILD
- // Virtual memory.
- getrlimit (RLIMIT_AS, &r);
- r.rlim_cur = limit;
- setrlimit (RLIMIT_AS, &r);
-#endif
-#endif
#endif
}
diff --git a/lib/TableGen/Record.cpp b/lib/TableGen/Record.cpp
index 83f7147dc9f6..b2636e1e6cb4 100644
--- a/lib/TableGen/Record.cpp
+++ b/lib/TableGen/Record.cpp
@@ -11,20 +11,28 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include <cassert>
#include <cstdint>
-#include <new>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
using namespace llvm;
@@ -162,7 +170,8 @@ RecTy *llvm::resolveTypes(RecTy *T1, RecTy *T2) {
// Initializer implementations
//===----------------------------------------------------------------------===//
-void Init::anchor() { }
+void Init::anchor() {}
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void Init::dump() const { return print(errs()); }
#endif
@@ -301,7 +310,6 @@ static Init *fixBitInit(const RecordVal *RV, Init *Before, Init *After) {
// resolveReferences - If there are any field references that refer to fields
// that have been filled in, we can propagate the values now.
-//
Init *BitsInit::resolveReferences(Record &R, const RecordVal *RV) const {
bool Changed = false;
SmallVector<Init *, 16> NewBits(getNumBits());
@@ -615,7 +623,7 @@ void UnOpInit::Profile(FoldingSetNodeID &ID) const {
Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
switch (getOpcode()) {
- case CAST: {
+ case CAST:
if (isa<StringRecTy>(getType())) {
if (StringInit *LHSs = dyn_cast<StringInit>(LHS))
return LHSs;
@@ -680,15 +688,15 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
}
}
break;
- }
- case HEAD: {
+
+ case HEAD:
if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
assert(!LHSl->empty() && "Empty list in head");
return LHSl->getElement(0);
}
break;
- }
- case TAIL: {
+
+ case TAIL:
if (ListInit *LHSl = dyn_cast<ListInit>(LHS)) {
assert(!LHSl->empty() && "Empty list in tail");
// Note the +1. We can't just pass the result of getValues()
@@ -696,16 +704,14 @@ Init *UnOpInit::Fold(Record *CurRec, MultiClass *CurMultiClass) const {
return ListInit::get(LHSl->getValues().slice(1), LHSl->getType());
}
break;
- }
- case EMPTY: {
+
+ case EMPTY:
if (ListInit *LHSl = dyn_cast<ListInit>(LHS))
return IntInit::get(LHSl->empty());
if (StringInit *LHSs = dyn_cast<StringInit>(LHS))
return IntInit::get(LHSs->getValue().empty());
-
break;
}
- }
return const_cast<UnOpInit *>(this);
}
@@ -948,7 +954,6 @@ static Init *EvaluateOperation(OpInit *RHSo, Init *LHS, Init *Arg,
static Init *ForeachHelper(Init *LHS, Init *MHS, Init *RHS, RecTy *Type,
Record *CurRec, MultiClass *CurMultiClass) {
-
OpInit *RHSo = dyn_cast<OpInit>(RHS);
if (!RHSo)
@@ -1245,7 +1250,7 @@ VarInit *VarInit::get(StringRef VN, RecTy *T) {
}
VarInit *VarInit::get(Init *VN, RecTy *T) {
- typedef std::pair<RecTy *, Init *> Key;
+ using Key = std::pair<RecTy *, Init *>;
static DenseMap<Key, VarInit*> ThePool;
Key TheKey(std::make_pair(T, VN));
@@ -1320,7 +1325,7 @@ Init *VarInit::resolveReferences(Record &R, const RecordVal *RV) const {
}
VarBitInit *VarBitInit::get(TypedInit *T, unsigned B) {
- typedef std::pair<TypedInit *, unsigned> Key;
+ using Key = std::pair<TypedInit *, unsigned>;
static DenseMap<Key, VarBitInit*> ThePool;
Key TheKey(std::make_pair(T, B));
@@ -1352,7 +1357,7 @@ Init *VarBitInit::resolveReferences(Record &R, const RecordVal *RV) const {
VarListElementInit *VarListElementInit::get(TypedInit *T,
unsigned E) {
- typedef std::pair<TypedInit *, unsigned> Key;
+ using Key = std::pair<TypedInit *, unsigned>;
static DenseMap<Key, VarListElementInit*> ThePool;
Key TheKey(std::make_pair(T, E));
@@ -1422,7 +1427,7 @@ std::string DefInit::getAsString() const {
}
FieldInit *FieldInit::get(Init *R, StringInit *FN) {
- typedef std::pair<Init *, StringInit *> Key;
+ using Key = std::pair<Init *, StringInit *>;
static DenseMap<Key, FieldInit*> ThePool;
Key TheKey(std::make_pair(R, FN));
diff --git a/lib/TableGen/SetTheory.cpp b/lib/TableGen/SetTheory.cpp
index a4d33051b4f7..733e0aeef623 100644
--- a/lib/TableGen/SetTheory.cpp
+++ b/lib/TableGen/SetTheory.cpp
@@ -12,18 +12,29 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/TableGen/SetTheory.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Format.h"
+#include "llvm/Support/SMLoc.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/SetTheory.h"
+#include <algorithm>
+#include <cstdint>
+#include <string>
+#include <utility>
using namespace llvm;
// Define the standard operators.
namespace {
-typedef SetTheory::RecSet RecSet;
-typedef SetTheory::RecVec RecVec;
+using RecSet = SetTheory::RecSet;
+using RecVec = SetTheory::RecVec;
// (add a, b, ...) Evaluate and union all arguments.
struct AddOp : public SetTheory::Operator {
@@ -237,13 +248,13 @@ struct FieldExpander : public SetTheory::Expander {
ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc());
}
};
+
} // end anonymous namespace
// Pin the vtables to this file.
void SetTheory::Operator::anchor() {}
void SetTheory::Expander::anchor() {}
-
SetTheory::SetTheory() {
addOperator("add", llvm::make_unique<AddOp>());
addOperator("sub", llvm::make_unique<SubOp>());
@@ -321,4 +332,3 @@ const RecVec *SetTheory::expand(Record *Set) {
// Set is not expandable.
return nullptr;
}
-
diff --git a/lib/Target/AArch64/AArch64.td b/lib/Target/AArch64/AArch64.td
index abe28460c83a..53eef79c4df3 100644
--- a/lib/Target/AArch64/AArch64.td
+++ b/lib/Target/AArch64/AArch64.td
@@ -362,6 +362,7 @@ def ProcThunderXT83 : SubtargetFeature<"thunderxt83", "ARMProcFamily",
def : ProcessorModel<"generic", NoSchedModel, [
FeatureFPARMv8,
+ FeatureFuseAES,
FeatureNEON,
FeaturePerfMon,
FeaturePostRAScheduler
diff --git a/lib/Target/AArch64/AArch64FastISel.cpp b/lib/Target/AArch64/AArch64FastISel.cpp
index e8fcf1a0e9b7..7bf2097c17ce 100644
--- a/lib/Target/AArch64/AArch64FastISel.cpp
+++ b/lib/Target/AArch64/AArch64FastISel.cpp
@@ -1282,6 +1282,10 @@ unsigned AArch64FastISel::emitAddSub_rr(bool UseAdd, MVT RetVT, unsigned LHSReg,
bool WantResult) {
assert(LHSReg && RHSReg && "Invalid register number.");
+ if (LHSReg == AArch64::SP || LHSReg == AArch64::WSP ||
+ RHSReg == AArch64::SP || RHSReg == AArch64::WSP)
+ return 0;
+
if (RetVT != MVT::i32 && RetVT != MVT::i64)
return 0;
@@ -1362,6 +1366,8 @@ unsigned AArch64FastISel::emitAddSub_rs(bool UseAdd, MVT RetVT, unsigned LHSReg,
uint64_t ShiftImm, bool SetFlags,
bool WantResult) {
assert(LHSReg && RHSReg && "Invalid register number.");
+ assert(LHSReg != AArch64::SP && LHSReg != AArch64::WSP &&
+ RHSReg != AArch64::SP && RHSReg != AArch64::WSP);
if (RetVT != MVT::i32 && RetVT != MVT::i64)
return 0;
@@ -1403,6 +1409,8 @@ unsigned AArch64FastISel::emitAddSub_rx(bool UseAdd, MVT RetVT, unsigned LHSReg,
uint64_t ShiftImm, bool SetFlags,
bool WantResult) {
assert(LHSReg && RHSReg && "Invalid register number.");
+ assert(LHSReg != AArch64::XZR && LHSReg != AArch64::WZR &&
+ RHSReg != AArch64::XZR && RHSReg != AArch64::WZR);
if (RetVT != MVT::i32 && RetVT != MVT::i64)
return 0;
diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp
index 059556a560c0..083ca2156598 100644
--- a/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -9366,7 +9366,7 @@ static SDValue splitStores(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
return SDValue();
StoreSDNode *S = cast<StoreSDNode>(N);
- if (S->isVolatile())
+ if (S->isVolatile() || S->isIndexed())
return SDValue();
SDValue StVal = S->getValue();
diff --git a/lib/Target/AArch64/AArch64SchedFalkorDetails.td b/lib/Target/AArch64/AArch64SchedFalkorDetails.td
index 7402bcf1346c..3d737402022d 100644
--- a/lib/Target/AArch64/AArch64SchedFalkorDetails.td
+++ b/lib/Target/AArch64/AArch64SchedFalkorDetails.td
@@ -160,6 +160,21 @@ def FalkorWr_1VX_1VY_10cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> {
let NumMicroOps = 2;
}
+def FalkorWr_1VX_1VY_12cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> {
+ let Latency = 12;
+ let NumMicroOps = 2;
+}
+
+def FalkorWr_1VX_1VY_14cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> {
+ let Latency = 14;
+ let NumMicroOps = 2;
+}
+
+def FalkorWr_1VX_1VY_21cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY]> {
+ let Latency = 21;
+ let NumMicroOps = 2;
+}
+
def FalkorWr_1GTOV_1VXVY_2cyc : SchedWriteRes<[FalkorUnitGTOV, FalkorUnitVXVY]> {
let Latency = 2;
let NumMicroOps = 2;
@@ -195,10 +210,10 @@ def FalkorWr_1X_1Z_8cyc : SchedWriteRes<[FalkorUnitX, FalkorUnitZ]> {
let ResourceCycles = [2, 8];
}
-def FalkorWr_1X_1Z_16cyc : SchedWriteRes<[FalkorUnitX, FalkorUnitZ]> {
- let Latency = 16;
+def FalkorWr_1X_1Z_11cyc : SchedWriteRes<[FalkorUnitX, FalkorUnitZ]> {
+ let Latency = 11;
let NumMicroOps = 2;
- let ResourceCycles = [2, 16];
+ let ResourceCycles = [2, 11];
}
def FalkorWr_1LD_1Z_3cyc : SchedWriteRes<[FalkorUnitLD, FalkorUnitZ]> {
@@ -289,9 +304,27 @@ def FalkorWr_1XYZ_1VSD_1ST_0cyc: SchedWriteRes<[FalkorUnitXYZ, FalkorUnitVSD, Fa
//===----------------------------------------------------------------------===//
// Define 4 micro-op types
-def FalkorWr_2VX_2VY_2cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY,
- FalkorUnitVX, FalkorUnitVY]> {
- let Latency = 2;
+def FalkorWr_2VX_2VY_14cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY,
+ FalkorUnitVX, FalkorUnitVY]> {
+ let Latency = 14;
+ let NumMicroOps = 4;
+}
+
+def FalkorWr_2VX_2VY_20cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY,
+ FalkorUnitVX, FalkorUnitVY]> {
+ let Latency = 20;
+ let NumMicroOps = 4;
+}
+
+def FalkorWr_2VX_2VY_21cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY,
+ FalkorUnitVX, FalkorUnitVY]> {
+ let Latency = 21;
+ let NumMicroOps = 4;
+}
+
+def FalkorWr_2VX_2VY_24cyc : SchedWriteRes<[FalkorUnitVX, FalkorUnitVY,
+ FalkorUnitVX, FalkorUnitVY]> {
+ let Latency = 24;
let NumMicroOps = 4;
}
@@ -575,7 +608,8 @@ def : InstRW<[FalkorWr_2VXVY_2cyc], (instregex "^FCM(EQ|LE|GE|GT|LT)(v2i64|v4i
def : InstRW<[FalkorWr_2VXVY_2cyc], (instrs FCVTLv4i16, FCVTLv2i32)>;
def : InstRW<[FalkorWr_2VXVY_2cyc], (instregex "^FRINT(A|I|M|N|P|X|Z)(v2f64|v4f32)$")>;
-def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instregex "^(FDIV|FSQRT)v2f32$")>;
+def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instrs FDIVv2f32)>;
+def : InstRW<[FalkorWr_1VX_1VY_12cyc],(instrs FSQRTv2f32)>;
def : InstRW<[FalkorWr_2VXVY_3cyc], (instregex "^(FABD|FADD(P)?|FSUB)(v2f64|v4f32)$")>;
@@ -592,7 +626,10 @@ def : InstRW<[FalkorWr_FMUL64_2VXVY_6cyc],
def : InstRW<[FalkorWr_3VXVY_4cyc], (instrs FCVTNv4i16, FCVTNv2i32, FCVTXNv2f32)>;
def : InstRW<[FalkorWr_3VXVY_5cyc], (instrs FCVTNv8i16, FCVTNv4i32, FCVTXNv4f32)>;
-def : InstRW<[FalkorWr_2VX_2VY_2cyc], (instregex "^(FDIV|FSQRT)(v2f64|v4f32)$")>;
+def : InstRW<[FalkorWr_2VX_2VY_14cyc],(instrs FDIVv2f64)>;
+def : InstRW<[FalkorWr_2VX_2VY_20cyc],(instrs FDIVv4f32)>;
+def : InstRW<[FalkorWr_2VX_2VY_21cyc],(instrs FSQRTv2f64)>;
+def : InstRW<[FalkorWr_2VX_2VY_24cyc],(instrs FSQRTv4f32)>;
def : InstRW<[FalkorWr_VMUL32_1VXVY_4cyc, FalkorReadVMA],
(instregex "^ML(A|S)(v8i8|v4i16|v2i32)(_indexed)?$")>;
@@ -1039,8 +1076,10 @@ def : InstRW<[FalkorWr_FMUL32_1VXVY_5cyc],
def : InstRW<[FalkorWr_FMUL64_1VXVY_6cyc],
(instregex "^F(N)?MULDrr$")>;
-def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instregex "^FDIV(S|D)rr$")>;
-def : InstRW<[FalkorWr_1VX_1VY_2cyc], (instregex "^FSQRT(S|D)r$")>;
+def : InstRW<[FalkorWr_1VX_1VY_10cyc],(instrs FDIVSrr)>;
+def : InstRW<[FalkorWr_1VX_1VY_14cyc],(instrs FDIVDrr)>;
+def : InstRW<[FalkorWr_1VX_1VY_12cyc],(instrs FSQRTSr)>;
+def : InstRW<[FalkorWr_1VX_1VY_21cyc],(instrs FSQRTDr)>;
def : InstRW<[FalkorWr_FMUL32_1VXVY_5cyc, ReadDefault, ReadDefault, FalkorReadFMA32],
(instregex "^F(N)?M(ADD|SUB)Srrr$")>;
@@ -1112,7 +1151,7 @@ def : InstRW<[FalkorWr_IMUL64_1X_5cyc, ReadDefault, ReadDefault, FalkorReadIMA64
(instregex "^M(ADD|SUB)Xrrr$")>;
def : InstRW<[FalkorWr_1X_1Z_8cyc], (instregex "^(S|U)DIVWr$")>;
-def : InstRW<[FalkorWr_1X_1Z_16cyc], (instregex "^(S|U)DIVXr$")>;
+def : InstRW<[FalkorWr_1X_1Z_11cyc], (instregex "^(S|U)DIVXr$")>;
def : InstRW<[FalkorWr_VMUL32_2VXVY_4cyc],
(instregex "^(S|U)MULLv.*$")>;
diff --git a/lib/Target/AArch64/AArch64Subtarget.cpp b/lib/Target/AArch64/AArch64Subtarget.cpp
index d3cab1ad3397..a9a9d5ce8429 100644
--- a/lib/Target/AArch64/AArch64Subtarget.cpp
+++ b/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -92,6 +92,10 @@ void AArch64Subtarget::initializeProperties() {
MaxInterleaveFactor = 4;
// FIXME: remove this to enable 64-bit SLP if performance looks good.
MinVectorRegisterBitWidth = 128;
+ CacheLineSize = 128;
+ PrefetchDistance = 820;
+ MinPrefetchStride = 2048;
+ MaxPrefetchIterationsAhead = 8;
break;
case Kryo:
MaxInterleaveFactor = 4;
diff --git a/lib/Target/AArch64/AArch64TargetTransformInfo.h b/lib/Target/AArch64/AArch64TargetTransformInfo.h
index d0299149c38c..290a1ca1f24b 100644
--- a/lib/Target/AArch64/AArch64TargetTransformInfo.h
+++ b/lib/Target/AArch64/AArch64TargetTransformInfo.h
@@ -78,7 +78,7 @@ public:
return 31;
}
- unsigned getRegisterBitWidth(bool Vector) {
+ unsigned getRegisterBitWidth(bool Vector) const {
if (Vector) {
if (ST->hasNEON())
return 128;
diff --git a/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp b/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp
index 8084d368c80f..6f3742ed039b 100644
--- a/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp
+++ b/lib/Target/AMDGPU/AMDGPUAlwaysInlinePass.cpp
@@ -9,7 +9,7 @@
//
/// \file
/// This pass marks all internal functions as always_inline and creates
-/// duplicates of all other functions a marks the duplicates as always_inline.
+/// duplicates of all other functions and marks the duplicates as always_inline.
//
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp b/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp
index 3c788fa1dcea..6f002860044c 100644
--- a/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp
+++ b/lib/Target/AMDGPU/AMDGPUAnnotateUniformValues.cpp
@@ -107,7 +107,7 @@ bool AMDGPUAnnotateUniformValues::isClobberedInFunction(LoadInst * Load) {
DFS(Start, Checklist);
for (auto &BB : Checklist) {
- BasicBlock::iterator StartIt = (BB == Load->getParent()) ?
+ BasicBlock::iterator StartIt = (!L && (BB == Load->getParent())) ?
BasicBlock::iterator(Load) : BB->end();
if (MDR->getPointerDependencyFrom(MemoryLocation(Ptr),
true, StartIt, BB, Load).isClobber())
diff --git a/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp b/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
index 251c2f9bb25a..f235313e4853 100644
--- a/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
+++ b/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp
@@ -138,7 +138,10 @@ private:
bool SelectMUBUFIntrinsicVOffset(SDValue Offset, SDValue &SOffset,
SDValue &ImmOffset, SDValue &VOffset) const;
- bool SelectFlat(SDValue Addr, SDValue &VAddr, SDValue &SLC) const;
+ bool SelectFlatAtomic(SDValue Addr, SDValue &VAddr,
+ SDValue &Offset, SDValue &SLC) const;
+ bool SelectFlatOffset(SDValue Addr, SDValue &VAddr,
+ SDValue &Offset, SDValue &SLC) const;
bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset,
bool &Imm) const;
@@ -1313,14 +1316,37 @@ bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicVOffset(SDValue Offset,
return true;
}
-bool AMDGPUDAGToDAGISel::SelectFlat(SDValue Addr,
- SDValue &VAddr,
- SDValue &SLC) const {
+bool AMDGPUDAGToDAGISel::SelectFlatOffset(SDValue Addr,
+ SDValue &VAddr,
+ SDValue &Offset,
+ SDValue &SLC) const {
+ int64_t OffsetVal = 0;
+
+ if (Subtarget->hasFlatInstOffsets() &&
+ CurDAG->isBaseWithConstantOffset(Addr)) {
+ SDValue N0 = Addr.getOperand(0);
+ SDValue N1 = Addr.getOperand(1);
+ uint64_t COffsetVal = cast<ConstantSDNode>(N1)->getZExtValue();
+ if (isUInt<12>(COffsetVal)) {
+ Addr = N0;
+ OffsetVal = COffsetVal;
+ }
+ }
+
VAddr = Addr;
+ Offset = CurDAG->getTargetConstant(OffsetVal, SDLoc(), MVT::i16);
SLC = CurDAG->getTargetConstant(0, SDLoc(), MVT::i1);
+
return true;
}
+bool AMDGPUDAGToDAGISel::SelectFlatAtomic(SDValue Addr,
+ SDValue &VAddr,
+ SDValue &Offset,
+ SDValue &SLC) const {
+ return SelectFlatOffset(Addr, VAddr, Offset, SLC);
+}
+
bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode,
SDValue &Offset, bool &Imm) const {
diff --git a/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index a7eac080f885..e54c887d6090 100644
--- a/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -126,8 +126,9 @@ bool AMDGPUInstructionSelector::selectG_STORE(MachineInstr &I) const {
MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(AMDGPU::FLAT_STORE_DWORD))
.add(I.getOperand(1))
.add(I.getOperand(0))
- .addImm(0)
- .addImm(0);
+ .addImm(0) // offset
+ .addImm(0) // glc
+ .addImm(0); // slc
// Now that we selected an opcode, we need to constrain the register
@@ -392,8 +393,9 @@ bool AMDGPUInstructionSelector::selectG_LOAD(MachineInstr &I) const {
MachineInstr *Flat = BuildMI(*BB, &I, DL, TII.get(Opcode))
.add(I.getOperand(0))
.addReg(PtrReg)
- .addImm(0)
- .addImm(0);
+ .addImm(0) // offset
+ .addImm(0) // glc
+ .addImm(0); // slc
bool Ret = constrainSelectedInstRegOperands(*Flat, TII, TRI, RBI);
I.eraseFromParent();
diff --git a/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index b889788c3426..790a69b84397 100644
--- a/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -34,6 +34,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo() {
const LLT P1 = LLT::pointer(1, 64);
const LLT P2 = LLT::pointer(2, 64);
+ setAction({G_ADD, S32}, Legal);
+
// FIXME: i1 operands to intrinsics should always be legal, but other i1
// values may not be legal. We need to figure out how to distinguish
// between these two scenarios.
diff --git a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
index dee3d2856701..0d6689bd04c4 100644
--- a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
+++ b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.cpp
@@ -195,7 +195,7 @@ unsigned AMDGPUTTIImpl::getNumberOfRegisters(bool Vec) {
return 4 * 128; // XXX - 4 channels. Should these count as vector instead?
}
-unsigned AMDGPUTTIImpl::getRegisterBitWidth(bool Vector) {
+unsigned AMDGPUTTIImpl::getRegisterBitWidth(bool Vector) const {
return Vector ? 0 : 32;
}
@@ -489,6 +489,19 @@ bool AMDGPUTTIImpl::isSourceOfDivergence(const Value *V) const {
return false;
}
+bool AMDGPUTTIImpl::isAlwaysUniform(const Value *V) const {
+ if (const IntrinsicInst *Intrinsic = dyn_cast<IntrinsicInst>(V)) {
+ switch (Intrinsic->getIntrinsicID()) {
+ default:
+ return false;
+ case Intrinsic::amdgcn_readfirstlane:
+ case Intrinsic::amdgcn_readlane:
+ return true;
+ }
+ }
+ return false;
+}
+
unsigned AMDGPUTTIImpl::getShuffleCost(TTI::ShuffleKind Kind, Type *Tp, int Index,
Type *SubTp) {
if (ST->hasVOP3PInsts()) {
diff --git a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
index e0024e21e82b..a60b1bb1b59c 100644
--- a/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
+++ b/lib/Target/AMDGPU/AMDGPUTargetTransformInfo.h
@@ -76,7 +76,7 @@ public:
}
unsigned getNumberOfRegisters(bool Vector);
- unsigned getRegisterBitWidth(bool Vector);
+ unsigned getRegisterBitWidth(bool Vector) const;
unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const;
bool isLegalToVectorizeMemChain(unsigned ChainSizeInBytes,
@@ -103,6 +103,7 @@ public:
int getVectorInstrCost(unsigned Opcode, Type *ValTy, unsigned Index);
bool isSourceOfDivergence(const Value *V) const;
+ bool isAlwaysUniform(const Value *V) const;
unsigned getFlatAddressSpace() const {
// Don't bother running InferAddressSpaces pass on graphics shaders which
diff --git a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index 16e3b7b4ebee..392e9d89bd9b 100644
--- a/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -285,6 +285,9 @@ public:
bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
+
+ bool isOffsetU12() const { return isImmTy(ImmTyOffset) && isUInt<12>(getImm()); }
+ bool isOffsetS13() const { return isImmTy(ImmTyOffset) && isInt<13>(getImm()); }
bool isGDS() const { return isImmTy(ImmTyGDS); }
bool isGLC() const { return isImmTy(ImmTyGLC); }
bool isSLC() const { return isImmTy(ImmTySLC); }
@@ -886,6 +889,10 @@ public:
return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
}
+ bool hasFlatOffsets() const {
+ return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
+ }
+
bool hasSGPR102_SGPR103() const {
return !isVI();
}
@@ -1034,6 +1041,7 @@ public:
AMDGPUOperand::Ptr defaultSMRDOffset8() const;
AMDGPUOperand::Ptr defaultSMRDOffset20() const;
AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
+ AMDGPUOperand::Ptr defaultOffsetU12() const;
OperandMatchResultTy parseOModOperand(OperandVector &Operands);
@@ -1970,6 +1978,15 @@ unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
}
}
+ if ((TSFlags & SIInstrFlags::FLAT) && !hasFlatOffsets()) {
+ // FIXME: Produces error without correct column reported.
+ auto OpNum =
+ AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::offset);
+ const auto &Op = Inst.getOperand(OpNum);
+ if (Op.getImm() != 0)
+ return Match_InvalidOperand;
+ }
+
return Match_Success;
}
@@ -3849,6 +3866,10 @@ AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
}
+AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetU12() const {
+ return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
+}
+
//===----------------------------------------------------------------------===//
// vop3
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/AMDGPU/FLATInstructions.td b/lib/Target/AMDGPU/FLATInstructions.td
index 8ba9efd42c70..98eda288bcac 100644
--- a/lib/Target/AMDGPU/FLATInstructions.td
+++ b/lib/Target/AMDGPU/FLATInstructions.td
@@ -7,7 +7,8 @@
//
//===----------------------------------------------------------------------===//
-def FLATAtomic : ComplexPattern<i64, 2, "SelectFlat">;
+def FLATAtomic : ComplexPattern<i64, 3, "SelectFlatAtomic", [], [], -10>;
+def FLATOffset : ComplexPattern<i64, 3, "SelectFlat", [], [], -10>;
//===----------------------------------------------------------------------===//
// FLAT classes
@@ -55,6 +56,8 @@ class FLAT_Real <bits<7> op, FLAT_Pseudo ps> :
// copy relevant pseudo op flags
let SubtargetPredicate = ps.SubtargetPredicate;
let AsmMatchConverter = ps.AsmMatchConverter;
+ let TSFlags = ps.TSFlags;
+ let UseNamedOperandTable = ps.UseNamedOperandTable;
// encoding fields
bits<8> vaddr;
@@ -63,10 +66,23 @@ class FLAT_Real <bits<7> op, FLAT_Pseudo ps> :
bits<1> slc;
bits<1> glc;
+ // Only valid on gfx9
+ bits<1> lds = 0; // XXX - What does this actually do?
+ bits<2> seg; // Segment, 00=flat, 01=scratch, 10=global, 11=reserved
+
+ // Signed offset. Highest bit ignored for flat and treated as 12-bit
+ // unsigned for flat acceses.
+ bits<13> offset;
+ bits<1> nv = 0; // XXX - What does this actually do?
+
// We don't use tfe right now, and it was removed in gfx9.
bits<1> tfe = 0;
- // 15-0 is reserved.
+ // Only valid on GFX9+
+ let Inst{12-0} = offset;
+ let Inst{13} = lds;
+ let Inst{15-14} = 0;
+
let Inst{16} = !if(ps.has_glc, glc, ps.glcValue);
let Inst{17} = slc;
let Inst{24-18} = op;
@@ -74,24 +90,30 @@ class FLAT_Real <bits<7> op, FLAT_Pseudo ps> :
let Inst{39-32} = vaddr;
let Inst{47-40} = !if(ps.has_data, vdata, ?);
// 54-48 is reserved.
- let Inst{55} = tfe;
+ let Inst{55} = nv; // nv on GFX9+, TFE before.
let Inst{63-56} = !if(ps.has_vdst, vdst, ?);
}
-class FLAT_Load_Pseudo <string opName, RegisterClass regClass> : FLAT_Pseudo<
+class FLAT_Load_Pseudo <string opName, RegisterClass regClass,
+ bit HasSignedOffset = 0> : FLAT_Pseudo<
opName,
(outs regClass:$vdst),
- (ins VReg_64:$vaddr, GLC:$glc, slc:$slc),
- " $vdst, $vaddr$glc$slc"> {
+ !if(HasSignedOffset,
+ (ins VReg_64:$vaddr, offset_s13:$offset, GLC:$glc, slc:$slc),
+ (ins VReg_64:$vaddr, offset_u12:$offset, GLC:$glc, slc:$slc)),
+ " $vdst, $vaddr$offset$glc$slc"> {
let has_data = 0;
let mayLoad = 1;
}
-class FLAT_Store_Pseudo <string opName, RegisterClass vdataClass> : FLAT_Pseudo<
+class FLAT_Store_Pseudo <string opName, RegisterClass vdataClass,
+ bit HasSignedOffset = 0> : FLAT_Pseudo<
opName,
(outs),
- (ins VReg_64:$vaddr, vdataClass:$vdata, GLC:$glc, slc:$slc),
- " $vaddr, $vdata$glc$slc"> {
+ !if(HasSignedOffset,
+ (ins VReg_64:$vaddr, vdataClass:$vdata, offset_s13:$offset, GLC:$glc, slc:$slc),
+ (ins VReg_64:$vaddr, vdataClass:$vdata, offset_u12:$offset, GLC:$glc, slc:$slc)),
+ " $vaddr, $vdata$offset$glc$slc"> {
let mayLoad = 0;
let mayStore = 1;
let has_vdst = 0;
@@ -103,12 +125,15 @@ multiclass FLAT_Atomic_Pseudo<
ValueType vt,
SDPatternOperator atomic = null_frag,
ValueType data_vt = vt,
- RegisterClass data_rc = vdst_rc> {
+ RegisterClass data_rc = vdst_rc,
+ bit HasSignedOffset = 0> {
def "" : FLAT_Pseudo <opName,
(outs),
- (ins VReg_64:$vaddr, data_rc:$vdata, slc:$slc),
- " $vaddr, $vdata$slc",
+ !if(HasSignedOffset,
+ (ins VReg_64:$vaddr, data_rc:$vdata, offset_s13:$offset, slc:$slc),
+ (ins VReg_64:$vaddr, data_rc:$vdata, offset_u12:$offset, slc:$slc)),
+ " $vaddr, $vdata$offset$slc",
[]>,
AtomicNoRet <NAME, 0> {
let mayLoad = 1;
@@ -121,10 +146,12 @@ multiclass FLAT_Atomic_Pseudo<
def _RTN : FLAT_Pseudo <opName,
(outs vdst_rc:$vdst),
- (ins VReg_64:$vaddr, data_rc:$vdata, slc:$slc),
- " $vdst, $vaddr, $vdata glc$slc",
+ !if(HasSignedOffset,
+ (ins VReg_64:$vaddr, data_rc:$vdata, offset_s13:$offset, slc:$slc),
+ (ins VReg_64:$vaddr, data_rc:$vdata, offset_u12:$offset, slc:$slc)),
+ " $vdst, $vaddr, $vdata$offset glc$slc",
[(set vt:$vdst,
- (atomic (FLATAtomic i64:$vaddr, i1:$slc), data_vt:$vdata))]>,
+ (atomic (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc), data_vt:$vdata))]>,
AtomicNoRet <NAME, 1> {
let mayLoad = 1;
let mayStore = 1;
@@ -312,31 +339,31 @@ def flat_truncstorei16 : flat_st <truncstorei16>;
// Patterns for global loads with no offset.
class FlatLoadPat <FLAT_Pseudo inst, SDPatternOperator node, ValueType vt> : Pat <
- (vt (node i64:$addr)),
- (inst $addr, 0, 0)
+ (vt (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc))),
+ (inst $vaddr, $offset, 0, $slc)
>;
class FlatLoadAtomicPat <FLAT_Pseudo inst, SDPatternOperator node, ValueType vt> : Pat <
- (vt (node i64:$addr)),
- (inst $addr, 1, 0)
+ (vt (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc))),
+ (inst $vaddr, $offset, 1, $slc)
>;
class FlatStorePat <FLAT_Pseudo inst, SDPatternOperator node, ValueType vt> : Pat <
- (node vt:$data, i64:$addr),
- (inst $addr, $data, 0, 0)
+ (node vt:$data, (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc)),
+ (inst $vaddr, $data, $offset, 0, $slc)
>;
class FlatStoreAtomicPat <FLAT_Pseudo inst, SDPatternOperator node, ValueType vt> : Pat <
// atomic store follows atomic binop convention so the address comes
// first.
- (node i64:$addr, vt:$data),
- (inst $addr, $data, 1, 0)
+ (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc), vt:$data),
+ (inst $vaddr, $data, $offset, 1, $slc)
>;
class FlatAtomicPat <FLAT_Pseudo inst, SDPatternOperator node, ValueType vt,
ValueType data_vt = vt> : Pat <
- (vt (node i64:$addr, data_vt:$data)),
- (inst $addr, $data, 0)
+ (vt (node (FLATAtomic i64:$vaddr, i16:$offset, i1:$slc), data_vt:$data)),
+ (inst $vaddr, $data, $offset, $slc)
>;
let Predicates = [isCIVI] in {
diff --git a/lib/Target/AMDGPU/SIISelLowering.cpp b/lib/Target/AMDGPU/SIISelLowering.cpp
index 599ee942d738..441f1ef4bd04 100644
--- a/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -567,9 +567,17 @@ bool SITargetLowering::getAddrModeArguments(IntrinsicInst *II,
}
bool SITargetLowering::isLegalFlatAddressingMode(const AddrMode &AM) const {
- // Flat instructions do not have offsets, and only have the register
- // address.
- return AM.BaseOffs == 0 && (AM.Scale == 0 || AM.Scale == 1);
+ if (!Subtarget->hasFlatInstOffsets()) {
+ // Flat instructions do not have offsets, and only have the register
+ // address.
+ return AM.BaseOffs == 0 && AM.Scale == 0;
+ }
+
+ // GFX9 added a 13-bit signed offset. When using regular flat instructions,
+ // the sign bit is ignored and is treated as a 12-bit unsigned offset.
+
+ // Just r + i
+ return isUInt<12>(AM.BaseOffs) && AM.Scale == 0;
}
bool SITargetLowering::isLegalMUBUFAddressingMode(const AddrMode &AM) const {
diff --git a/lib/Target/AMDGPU/SIInstrInfo.cpp b/lib/Target/AMDGPU/SIInstrInfo.cpp
index 58c05cf16f15..1097814e99ce 100644
--- a/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -468,13 +468,11 @@ void SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Builder.addReg(RI.getSubReg(SrcReg, SubIdx));
- if (Idx == SubIndices.size() - 1)
- Builder.addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
-
if (Idx == 0)
Builder.addReg(DestReg, RegState::Define | RegState::Implicit);
- Builder.addReg(SrcReg, RegState::Implicit);
+ bool UseKill = KillSrc && Idx == SubIndices.size() - 1;
+ Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
}
}
@@ -2331,11 +2329,12 @@ static bool isSubRegOf(const SIRegisterInfo &TRI,
bool SIInstrInfo::verifyInstruction(const MachineInstr &MI,
StringRef &ErrInfo) const {
uint16_t Opcode = MI.getOpcode();
-
if (SIInstrInfo::isGenericOpcode(MI.getOpcode()))
return true;
- const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const MachineRegisterInfo &MRI = MF->getRegInfo();
+
int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
@@ -2565,6 +2564,14 @@ bool SIInstrInfo::verifyInstruction(const MachineInstr &MI,
}
}
+ if (isFLAT(MI) && !MF->getSubtarget<SISubtarget>().hasFlatInstOffsets()) {
+ const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
+ if (Offset->getImm() != 0) {
+ ErrInfo = "subtarget does not support offsets in flat instructions";
+ return false;
+ }
+ }
+
return true;
}
diff --git a/lib/Target/AMDGPU/SIInstrInfo.td b/lib/Target/AMDGPU/SIInstrInfo.td
index 445bf79a7814..470a47b02443 100644
--- a/lib/Target/AMDGPU/SIInstrInfo.td
+++ b/lib/Target/AMDGPU/SIInstrInfo.td
@@ -492,11 +492,21 @@ class NamedOperandU8<string Name, AsmOperandClass MatchClass> : Operand<i8> {
let ParserMatchClass = MatchClass;
}
+class NamedOperandU12<string Name, AsmOperandClass MatchClass> : Operand<i16> {
+ let PrintMethod = "print"#Name;
+ let ParserMatchClass = MatchClass;
+}
+
class NamedOperandU16<string Name, AsmOperandClass MatchClass> : Operand<i16> {
let PrintMethod = "print"#Name;
let ParserMatchClass = MatchClass;
}
+class NamedOperandS13<string Name, AsmOperandClass MatchClass> : Operand<i16> {
+ let PrintMethod = "print"#Name;
+ let ParserMatchClass = MatchClass;
+}
+
class NamedOperandU32<string Name, AsmOperandClass MatchClass> : Operand<i32> {
let PrintMethod = "print"#Name;
let ParserMatchClass = MatchClass;
@@ -514,6 +524,8 @@ def offen : NamedOperandBit<"Offen", NamedMatchClass<"Offen">>;
def idxen : NamedOperandBit<"Idxen", NamedMatchClass<"Idxen">>;
def addr64 : NamedOperandBit<"Addr64", NamedMatchClass<"Addr64">>;
+def offset_u12 : NamedOperandU12<"Offset", NamedMatchClass<"OffsetU12">>;
+def offset_s13 : NamedOperandS13<"Offset", NamedMatchClass<"OffsetS13">>;
def offset : NamedOperandU16<"Offset", NamedMatchClass<"Offset">>;
def offset0 : NamedOperandU8<"Offset0", NamedMatchClass<"Offset0">>;
def offset1 : NamedOperandU8<"Offset1", NamedMatchClass<"Offset1">>;
diff --git a/lib/Target/ARM/ARMCallLowering.cpp b/lib/Target/ARM/ARMCallLowering.cpp
index a7ac9a1dca6e..e498f70b820d 100644
--- a/lib/Target/ARM/ARMCallLowering.cpp
+++ b/lib/Target/ARM/ARMCallLowering.cpp
@@ -35,9 +35,19 @@ ARMCallLowering::ARMCallLowering(const ARMTargetLowering &TLI)
static bool isSupportedType(const DataLayout &DL, const ARMTargetLowering &TLI,
Type *T) {
- if (T->isArrayTy() || T->isStructTy())
+ if (T->isArrayTy())
return true;
+ if (T->isStructTy()) {
+ // For now we only allow homogeneous structs that we can manipulate with
+ // G_MERGE_VALUES and G_UNMERGE_VALUES
+ auto StructT = cast<StructType>(T);
+ for (unsigned i = 1, e = StructT->getNumElements(); i != e; ++i)
+ if (StructT->getElementType(i) != StructT->getElementType(0))
+ return false;
+ return true;
+ }
+
EVT VT = TLI.getValueType(DL, T, true);
if (!VT.isSimple() || VT.isVector() ||
!(VT.isInteger() || VT.isFloatingPoint()))
@@ -220,12 +230,16 @@ bool ARMCallLowering::lowerReturnVal(MachineIRBuilder &MIRBuilder,
return false;
SmallVector<ArgInfo, 4> SplitVTs;
+ SmallVector<unsigned, 4> Regs;
ArgInfo RetInfo(VReg, Val->getType());
setArgFlags(RetInfo, AttributeList::ReturnIndex, DL, F);
splitToValueTypes(RetInfo, SplitVTs, MF, [&](unsigned Reg, uint64_t Offset) {
- MIRBuilder.buildExtract(Reg, VReg, Offset);
+ Regs.push_back(Reg);
});
+ if (Regs.size() > 1)
+ MIRBuilder.buildUnmerge(Regs, VReg);
+
CCAssignFn *AssignFn =
TLI.CCAssignFnForReturn(F.getCallingConv(), F.isVarArg());
@@ -344,26 +358,6 @@ struct IncomingValueHandler : public CallLowering::ValueHandler {
return 1;
}
- /// Merge the values in \p SrcRegs into \p DstReg at offsets \p SrcOffsets.
- /// Note that the source registers are not required to have homogeneous types,
- /// so we use G_INSERT rather than G_MERGE_VALUES.
- // FIXME: Use G_MERGE_VALUES if the types are homogeneous.
- void mergeRegisters(unsigned DstReg, ArrayRef<unsigned> SrcRegs,
- ArrayRef<uint64_t> SrcOffsets) {
- LLT Ty = MRI.getType(DstReg);
-
- unsigned Dst = MRI.createGenericVirtualRegister(Ty);
- MIRBuilder.buildUndef(Dst);
-
- for (unsigned i = 0; i < SrcRegs.size(); ++i) {
- unsigned Tmp = MRI.createGenericVirtualRegister(Ty);
- MIRBuilder.buildInsert(Tmp, Dst, SrcRegs[i], SrcOffsets[i]);
- Dst = Tmp;
- }
-
- MIRBuilder.buildCopy(DstReg, Dst);
- }
-
/// Marking a physical register as used is different between formal
/// parameters, where it's a basic block live-in, and call returns, where it's
/// an implicit-def of the call instruction.
@@ -413,22 +407,19 @@ bool ARMCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder,
SmallVector<ArgInfo, 8> ArgInfos;
SmallVector<unsigned, 4> SplitRegs;
- SmallVector<uint64_t, 4> RegOffsets;
unsigned Idx = 0;
for (auto &Arg : F.args()) {
ArgInfo AInfo(VRegs[Idx], Arg.getType());
setArgFlags(AInfo, Idx + AttributeList::FirstArgIndex, DL, F);
SplitRegs.clear();
- RegOffsets.clear();
splitToValueTypes(AInfo, ArgInfos, MF, [&](unsigned Reg, uint64_t Offset) {
SplitRegs.push_back(Reg);
- RegOffsets.push_back(Offset);
});
if (!SplitRegs.empty())
- ArgHandler.mergeRegisters(VRegs[Idx], SplitRegs, RegOffsets);
+ MIRBuilder.buildMerge(VRegs[Idx], SplitRegs);
Idx++;
}
@@ -490,9 +481,13 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
if (!Arg.IsFixed)
return false;
+ SmallVector<unsigned, 8> Regs;
splitToValueTypes(Arg, ArgInfos, MF, [&](unsigned Reg, uint64_t Offset) {
- MIRBuilder.buildExtract(Reg, Arg.Reg, Offset);
+ Regs.push_back(Reg);
});
+
+ if (Regs.size() > 1)
+ MIRBuilder.buildUnmerge(Regs, Arg.Reg);
}
auto ArgAssignFn = TLI.CCAssignFnForCall(CallConv, /*IsVarArg=*/false);
@@ -508,11 +503,9 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
return false;
ArgInfos.clear();
- SmallVector<uint64_t, 8> RegOffsets;
SmallVector<unsigned, 8> SplitRegs;
splitToValueTypes(OrigRet, ArgInfos, MF,
[&](unsigned Reg, uint64_t Offset) {
- RegOffsets.push_back(Offset);
SplitRegs.push_back(Reg);
});
@@ -521,10 +514,10 @@ bool ARMCallLowering::lowerCall(MachineIRBuilder &MIRBuilder,
if (!handleAssignments(MIRBuilder, ArgInfos, RetHandler))
return false;
- if (!RegOffsets.empty()) {
+ if (!SplitRegs.empty()) {
// We have split the value and allocated each individual piece, now build
// it up again.
- RetHandler.mergeRegisters(OrigRet.Reg, SplitRegs, RegOffsets);
+ MIRBuilder.buildMerge(OrigRet.Reg, SplitRegs);
}
}
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index 817b567db767..5d887c4fcbf2 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -2010,7 +2010,8 @@ def VFNMAD : ADbI<0b11101, 0b01, 1, 0,
[(set DPR:$Dd,(fsub_mlx (fneg (fmul_su DPR:$Dn,DPR:$Dm)),
(f64 DPR:$Ddin)))]>,
RegConstraint<"$Ddin = $Dd">,
- Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>;
+ Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>,
+ Sched<[WriteFPMAC64, ReadFPMAC, ReadFPMUL, ReadFPMUL]>;
def VFNMAS : ASbI<0b11101, 0b01, 1, 0,
(outs SPR:$Sd), (ins SPR:$Sdin, SPR:$Sn, SPR:$Sm),
@@ -2018,7 +2019,8 @@ def VFNMAS : ASbI<0b11101, 0b01, 1, 0,
[(set SPR:$Sd, (fsub_mlx (fneg (fmul_su SPR:$Sn, SPR:$Sm)),
SPR:$Sdin))]>,
RegConstraint<"$Sdin = $Sd">,
- Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]> {
+ Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]>,
+ Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]> {
// Some single precision VFP instructions may be executed on both NEON and
// VFP pipelines.
}
@@ -2028,7 +2030,8 @@ def VFNMAH : AHbI<0b11101, 0b01, 1, 0,
IIC_fpFMAC16, "vfnma", ".f16\t$Sd, $Sn, $Sm",
[]>,
RegConstraint<"$Sdin = $Sd">,
- Requires<[HasFullFP16,UseFusedMAC]>;
+ Requires<[HasFullFP16,UseFusedMAC]>,
+ Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]>;
def : Pat<(fsub_mlx (fneg (fmul_su DPR:$a, (f64 DPR:$b))), DPR:$dstin),
(VFNMAD DPR:$dstin, DPR:$a, DPR:$b)>,
@@ -2059,14 +2062,16 @@ def VFNMSD : ADbI<0b11101, 0b01, 0, 0,
[(set DPR:$Dd, (fsub_mlx (fmul_su DPR:$Dn, DPR:$Dm),
(f64 DPR:$Ddin)))]>,
RegConstraint<"$Ddin = $Dd">,
- Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>;
+ Requires<[HasVFP4,HasDPVFP,UseFusedMAC]>,
+ Sched<[WriteFPMAC64, ReadFPMAC, ReadFPMUL, ReadFPMUL]>;
def VFNMSS : ASbI<0b11101, 0b01, 0, 0,
(outs SPR:$Sd), (ins SPR:$Sdin, SPR:$Sn, SPR:$Sm),
IIC_fpFMAC32, "vfnms", ".f32\t$Sd, $Sn, $Sm",
[(set SPR:$Sd, (fsub_mlx (fmul_su SPR:$Sn, SPR:$Sm), SPR:$Sdin))]>,
RegConstraint<"$Sdin = $Sd">,
- Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]> {
+ Requires<[HasVFP4,DontUseNEONForFP,UseFusedMAC]>,
+ Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]> {
// Some single precision VFP instructions may be executed on both NEON and
// VFP pipelines.
}
@@ -2076,7 +2081,8 @@ def VFNMSH : AHbI<0b11101, 0b01, 0, 0,
IIC_fpFMAC16, "vfnms", ".f16\t$Sd, $Sn, $Sm",
[]>,
RegConstraint<"$Sdin = $Sd">,
- Requires<[HasFullFP16,UseFusedMAC]>;
+ Requires<[HasFullFP16,UseFusedMAC]>,
+ Sched<[WriteFPMAC32, ReadFPMAC, ReadFPMUL, ReadFPMUL]>;
def : Pat<(fsub_mlx (fmul_su DPR:$a, (f64 DPR:$b)), DPR:$dstin),
(VFNMSD DPR:$dstin, DPR:$a, DPR:$b)>,
diff --git a/lib/Target/ARM/ARMLegalizerInfo.cpp b/lib/Target/ARM/ARMLegalizerInfo.cpp
index 2d490b7c303e..a706079d9866 100644
--- a/lib/Target/ARM/ARMLegalizerInfo.cpp
+++ b/lib/Target/ARM/ARMLegalizerInfo.cpp
@@ -12,8 +12,10 @@
//===----------------------------------------------------------------------===//
#include "ARMLegalizerInfo.h"
+#include "ARMCallLowering.h"
#include "ARMSubtarget.h"
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "llvm/CodeGen/LowLevelType.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/DerivedTypes.h"
@@ -63,6 +65,16 @@ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
setAction({Op, s32}, Libcall);
}
+ // FIXME: Support s8 and s16 as well
+ for (unsigned Op : {G_SREM, G_UREM})
+ if (ST.hasDivideInARMMode())
+ setAction({Op, s32}, Lower);
+ else if (ST.isTargetAEABI() || ST.isTargetGNUAEABI() ||
+ ST.isTargetMuslAEABI())
+ setAction({Op, s32}, Custom);
+ else
+ setAction({Op, s32}, Libcall);
+
for (unsigned Op : {G_SEXT, G_ZEXT}) {
setAction({Op, s32}, Legal);
for (auto Ty : {s1, s8, s16})
@@ -134,5 +146,38 @@ bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
}
return true;
}
+ case G_SREM:
+ case G_UREM: {
+ unsigned OriginalResult = MI.getOperand(0).getReg();
+ auto Size = MRI.getType(OriginalResult).getSizeInBits();
+ if (Size != 32)
+ return false;
+
+ auto Libcall =
+ MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
+
+ // Our divmod libcalls return a struct containing the quotient and the
+ // remainder. We need to create a virtual register for it.
+ auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
+ Type *ArgTy = Type::getInt32Ty(Ctx);
+ StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);
+ auto RetVal = MRI.createGenericVirtualRegister(
+ getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout()));
+
+ auto Status = replaceWithLibcall(MI, MIRBuilder, Libcall, {RetVal, RetTy},
+ {{MI.getOperand(1).getReg(), ArgTy},
+ {MI.getOperand(2).getReg(), ArgTy}});
+ if (Status != LegalizerHelper::Legalized)
+ return false;
+
+ // The remainder is the second result of divmod. Split the return value into
+ // a new, unused register for the quotient and the destination of the
+ // original instruction for the remainder.
+ MIRBuilder.buildUnmerge(
+ {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult},
+ RetVal);
+
+ return LegalizerHelper::Legalized;
+ }
}
}
diff --git a/lib/Target/ARM/ARMTargetTransformInfo.h b/lib/Target/ARM/ARMTargetTransformInfo.h
index 7de0543dfa5e..8a1a37863877 100644
--- a/lib/Target/ARM/ARMTargetTransformInfo.h
+++ b/lib/Target/ARM/ARMTargetTransformInfo.h
@@ -78,7 +78,7 @@ public:
return 13;
}
- unsigned getRegisterBitWidth(bool Vector) {
+ unsigned getRegisterBitWidth(bool Vector) const {
if (Vector) {
if (ST->hasNEON())
return 128;
diff --git a/lib/Target/BPF/BPFAsmPrinter.cpp b/lib/Target/BPF/BPFAsmPrinter.cpp
index fcd903b7a4a8..9397c78f3dff 100644
--- a/lib/Target/BPF/BPFAsmPrinter.cpp
+++ b/lib/Target/BPF/BPFAsmPrinter.cpp
@@ -35,14 +35,15 @@ using namespace llvm;
namespace {
class BPFAsmPrinter : public AsmPrinter {
public:
- explicit BPFAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
+ explicit BPFAsmPrinter(TargetMachine &TM,
+ std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)) {}
StringRef getPassName() const override { return "BPF Assembly Printer"; }
void EmitInstruction(const MachineInstr *MI) override;
};
-}
+} // namespace
void BPFAsmPrinter::EmitInstruction(const MachineInstr *MI) {
diff --git a/lib/Target/BPF/BPFISelDAGToDAG.cpp b/lib/Target/BPF/BPFISelDAGToDAG.cpp
index 279cdb1a89b4..7d5fb6ca17b9 100644
--- a/lib/Target/BPF/BPFISelDAGToDAG.cpp
+++ b/lib/Target/BPF/BPFISelDAGToDAG.cpp
@@ -22,11 +22,14 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/IR/Constants.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
+
using namespace llvm;
#define DEBUG_TYPE "bpf-isel"
@@ -42,6 +45,8 @@ public:
return "BPF DAG->DAG Pattern Instruction Selection";
}
+ void PreprocessISelDAG() override;
+
private:
// Include the pieces autogenerated from the target description.
#include "BPFGenDAGISel.inc"
@@ -51,15 +56,31 @@ private:
// Complex Pattern for address selection.
bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
+
+ // Find constants from a constant structure
+ typedef std::vector<unsigned char> val_vec_type;
+ bool fillGenericConstant(const DataLayout &DL, const Constant *CV,
+ val_vec_type &Vals, uint64_t Offset);
+ bool fillConstantDataArray(const DataLayout &DL, const ConstantDataArray *CDA,
+ val_vec_type &Vals, int Offset);
+ bool fillConstantArray(const DataLayout &DL, const ConstantArray *CA,
+ val_vec_type &Vals, int Offset);
+ bool fillConstantStruct(const DataLayout &DL, const ConstantStruct *CS,
+ val_vec_type &Vals, int Offset);
+ bool getConstantFieldValue(const GlobalAddressSDNode *Node, uint64_t Offset,
+ uint64_t Size, unsigned char *ByteSeq);
+
+ // Mapping from ConstantStruct global value to corresponding byte-list values
+ std::map<const void *, val_vec_type> cs_vals_;
};
-}
+} // namespace
// ComplexPattern used on BPF Load/Store instructions
bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
// if Address is FI, get the TargetFrameIndex.
SDLoc DL(Addr);
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
- Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
return true;
}
@@ -85,13 +106,14 @@ bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
}
}
- Base = Addr;
+ Base = Addr;
Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
return true;
}
// ComplexPattern used on BPF FI instruction
-bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
+bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
SDLoc DL(Addr);
if (!CurDAG->isBaseWithConstantOffset(Addr))
@@ -102,8 +124,7 @@ bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset)
if (isInt<16>(CN->getSExtValue())) {
// If the first operand is a FI, get the TargetFI Node
- if (FrameIndexSDNode *FIN =
- dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
+ if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
else
return false;
@@ -129,7 +150,8 @@ void BPFDAGToDAGISel::Select(SDNode *Node) {
// tablegen selection should be handled here.
switch (Opcode) {
- default: break;
+ default:
+ break;
case ISD::SDIV: {
DebugLoc Empty;
const DebugLoc &DL = Node->getDebugLoc();
@@ -181,6 +203,210 @@ void BPFDAGToDAGISel::Select(SDNode *Node) {
SelectCode(Node);
}
+void BPFDAGToDAGISel::PreprocessISelDAG() {
+ // Iterate through all nodes, only interested in loads from ConstantStruct
+ // ConstantArray should have converted by IR->DAG processing
+ for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
+ E = CurDAG->allnodes_end();
+ I != E;) {
+ SDNode *Node = &*I++;
+ unsigned Opcode = Node->getOpcode();
+ if (Opcode != ISD::LOAD)
+ continue;
+
+ unsigned char new_val[8]; // hold up the constant values replacing loads.
+ bool to_replace = false;
+ SDLoc DL(Node);
+ const LoadSDNode *LD = cast<LoadSDNode>(Node);
+ uint64_t size = LD->getMemOperand()->getSize();
+ if (!size || size > 8 || (size & (size - 1)))
+ continue;
+
+ SDNode *LDAddrNode = LD->getOperand(1).getNode();
+ // Match LDAddr against either global_addr or (global_addr + offset)
+ unsigned opcode = LDAddrNode->getOpcode();
+ if (opcode == ISD::ADD) {
+ SDValue OP1 = LDAddrNode->getOperand(0);
+ SDValue OP2 = LDAddrNode->getOperand(1);
+
+ // We want to find the pattern global_addr + offset
+ SDNode *OP1N = OP1.getNode();
+ if (OP1N->getOpcode() <= ISD::BUILTIN_OP_END ||
+ OP1N->getNumOperands() == 0)
+ continue;
+
+ DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
+
+ const GlobalAddressSDNode *GADN =
+ dyn_cast<GlobalAddressSDNode>(OP1N->getOperand(0).getNode());
+ const ConstantSDNode *CDN = dyn_cast<ConstantSDNode>(OP2.getNode());
+ if (GADN && CDN)
+ to_replace =
+ getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val);
+ } else if (LDAddrNode->getOpcode() > ISD::BUILTIN_OP_END &&
+ LDAddrNode->getNumOperands() > 0) {
+ DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
+
+ SDValue OP1 = LDAddrNode->getOperand(0);
+ if (const GlobalAddressSDNode *GADN =
+ dyn_cast<GlobalAddressSDNode>(OP1.getNode()))
+ to_replace = getConstantFieldValue(GADN, 0, size, new_val);
+ }
+
+ if (!to_replace)
+ continue;
+
+ // replacing the old with a new value
+ uint64_t val;
+ if (size == 1)
+ val = *(uint8_t *)new_val;
+ else if (size == 2)
+ val = *(uint16_t *)new_val;
+ else if (size == 4)
+ val = *(uint32_t *)new_val;
+ else {
+ val = *(uint64_t *)new_val;
+ }
+
+ DEBUG(dbgs() << "Replacing load of size " << size << " with constant "
+ << val << '\n');
+ SDValue NVal = CurDAG->getConstant(val, DL, MVT::i64);
+
+ // After replacement, the current node is dead, we need to
+ // go backward one step to make iterator still work
+ I--;
+ SDValue From[] = {SDValue(Node, 0), SDValue(Node, 1)};
+ SDValue To[] = {NVal, NVal};
+ CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
+ I++;
+ // It is safe to delete node now
+ CurDAG->DeleteNode(Node);
+ }
+}
+
+bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node,
+ uint64_t Offset, uint64_t Size,
+ unsigned char *ByteSeq) {
+ const GlobalVariable *V = dyn_cast<GlobalVariable>(Node->getGlobal());
+
+ if (!V || !V->hasInitializer())
+ return false;
+
+ const Constant *Init = V->getInitializer();
+ const DataLayout &DL = CurDAG->getDataLayout();
+ val_vec_type TmpVal;
+
+ auto it = cs_vals_.find(static_cast<const void *>(Init));
+ if (it != cs_vals_.end()) {
+ TmpVal = it->second;
+ } else {
+ uint64_t total_size = 0;
+ if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(Init))
+ total_size =
+ DL.getStructLayout(cast<StructType>(CS->getType()))->getSizeInBytes();
+ else if (const ConstantArray *CA = dyn_cast<ConstantArray>(Init))
+ total_size = DL.getTypeAllocSize(CA->getType()->getElementType()) *
+ CA->getNumOperands();
+ else
+ return false;
+
+ val_vec_type Vals(total_size, 0);
+ if (fillGenericConstant(DL, Init, Vals, 0) == false)
+ return false;
+ cs_vals_[static_cast<const void *>(Init)] = Vals;
+ TmpVal = std::move(Vals);
+ }
+
+ // test whether host endianness matches target
+ uint8_t test_buf[2];
+ uint16_t test_val = 0x2345;
+ if (DL.isLittleEndian())
+ support::endian::write16le(test_buf, test_val);
+ else
+ support::endian::write16be(test_buf, test_val);
+
+ bool endian_match = *(uint16_t *)test_buf == test_val;
+ for (uint64_t i = Offset, j = 0; i < Offset + Size; i++, j++)
+ ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[Offset + Size - 1 - j];
+
+ return true;
+}
+
+bool BPFDAGToDAGISel::fillGenericConstant(const DataLayout &DL,
+ const Constant *CV,
+ val_vec_type &Vals, uint64_t Offset) {
+ uint64_t Size = DL.getTypeAllocSize(CV->getType());
+
+ if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
+ return true; // already done
+
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
+ uint64_t val = CI->getZExtValue();
+ DEBUG(dbgs() << "Byte array at offset " << Offset << " with value " << val
+ << '\n');
+
+ if (Size > 8 || (Size & (Size - 1)))
+ return false;
+
+ // Store based on target endian
+ for (uint64_t i = 0; i < Size; ++i) {
+ Vals[Offset + i] = DL.isLittleEndian()
+ ? ((val >> (i * 8)) & 0xFF)
+ : ((val >> ((Size - i - 1) * 8)) & 0xFF);
+ }
+ return true;
+ }
+
+ if (const ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(CV))
+ return fillConstantDataArray(DL, CDA, Vals, Offset);
+
+ if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV))
+ return fillConstantArray(DL, CA, Vals, Offset);
+
+ if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
+ return fillConstantStruct(DL, CVS, Vals, Offset);
+
+ return false;
+}
+
+bool BPFDAGToDAGISel::fillConstantDataArray(const DataLayout &DL,
+ const ConstantDataArray *CDA,
+ val_vec_type &Vals, int Offset) {
+ for (unsigned i = 0, e = CDA->getNumElements(); i != e; ++i) {
+ if (fillGenericConstant(DL, CDA->getElementAsConstant(i), Vals, Offset) ==
+ false)
+ return false;
+ Offset += DL.getTypeAllocSize(CDA->getElementAsConstant(i)->getType());
+ }
+
+ return true;
+}
+
+bool BPFDAGToDAGISel::fillConstantArray(const DataLayout &DL,
+ const ConstantArray *CA,
+ val_vec_type &Vals, int Offset) {
+ for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
+ if (fillGenericConstant(DL, CA->getOperand(i), Vals, Offset) == false)
+ return false;
+ Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType());
+ }
+
+ return true;
+}
+
+bool BPFDAGToDAGISel::fillConstantStruct(const DataLayout &DL,
+ const ConstantStruct *CS,
+ val_vec_type &Vals, int Offset) {
+ const StructLayout *Layout = DL.getStructLayout(CS->getType());
+ for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
+ const Constant *Field = CS->getOperand(i);
+ uint64_t SizeSoFar = Layout->getElementOffset(i);
+ if (fillGenericConstant(DL, Field, Vals, Offset + SizeSoFar) == false)
+ return false;
+ }
+ return true;
+}
+
FunctionPass *llvm::createBPFISelDag(BPFTargetMachine &TM) {
return new BPFDAGToDAGISel(TM);
}
diff --git a/lib/Target/BPF/BPFInstrInfo.td b/lib/Target/BPF/BPFInstrInfo.td
index c6c0ff587c6b..5ad777268208 100644
--- a/lib/Target/BPF/BPFInstrInfo.td
+++ b/lib/Target/BPF/BPFInstrInfo.td
@@ -51,7 +51,7 @@ def u64imm : Operand<i64> {
let PrintMethod = "printImm64Operand";
}
-def i64immSExt32 : PatLeaf<(imm),
+def i64immSExt32 : PatLeaf<(i64 imm),
[{return isInt<32>(N->getSExtValue()); }]>;
// Addressing modes.
@@ -67,17 +67,17 @@ def MEMri : Operand<i64> {
}
// Conditional code predicates - used for pattern matching for jump instructions
-def BPF_CC_EQ : PatLeaf<(imm),
+def BPF_CC_EQ : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETEQ);}]>;
-def BPF_CC_NE : PatLeaf<(imm),
+def BPF_CC_NE : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETNE);}]>;
-def BPF_CC_GE : PatLeaf<(imm),
+def BPF_CC_GE : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETGE);}]>;
-def BPF_CC_GT : PatLeaf<(imm),
+def BPF_CC_GT : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETGT);}]>;
-def BPF_CC_GTU : PatLeaf<(imm),
+def BPF_CC_GTU : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETUGT);}]>;
-def BPF_CC_GEU : PatLeaf<(imm),
+def BPF_CC_GEU : PatLeaf<(i64 imm),
[{return (N->getZExtValue() == ISD::SETUGE);}]>;
// jump instructions
diff --git a/lib/Target/Hexagon/HexagonGenMux.cpp b/lib/Target/Hexagon/HexagonGenMux.cpp
index 3c37d9ebb0eb..11ac5454f604 100644
--- a/lib/Target/Hexagon/HexagonGenMux.cpp
+++ b/lib/Target/Hexagon/HexagonGenMux.cpp
@@ -59,9 +59,7 @@ namespace {
public:
static char ID;
- HexagonGenMux() : MachineFunctionPass(ID), HII(nullptr), HRI(nullptr) {
- initializeHexagonGenMuxPass(*PassRegistry::getPassRegistry());
- }
+ HexagonGenMux() : MachineFunctionPass(ID) {}
StringRef getPassName() const override {
return "Hexagon generate mux instructions";
@@ -79,8 +77,8 @@ namespace {
}
private:
- const HexagonInstrInfo *HII;
- const HexagonRegisterInfo *HRI;
+ const HexagonInstrInfo *HII = nullptr;
+ const HexagonRegisterInfo *HRI = nullptr;
struct CondsetInfo {
unsigned PredR = 0;
@@ -134,7 +132,7 @@ namespace {
} // end anonymous namespace
-INITIALIZE_PASS(HexagonGenMux, "hexagon-mux",
+INITIALIZE_PASS(HexagonGenMux, "hexagon-gen-mux",
"Hexagon generate mux instructions", false, false)
void HexagonGenMux::getSubRegs(unsigned Reg, BitVector &SRs) const {
@@ -297,12 +295,15 @@ bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {
unsigned SR1 = Src1->isReg() ? Src1->getReg() : 0;
unsigned SR2 = Src2->isReg() ? Src2->getReg() : 0;
bool Failure = false, CanUp = true, CanDown = true;
+ bool Used1 = false, Used2 = false;
for (unsigned X = MinX+1; X < MaxX; X++) {
const DefUseInfo &DU = DUM.lookup(X);
if (DU.Defs[PR] || DU.Defs[DR] || DU.Uses[DR]) {
Failure = true;
break;
}
+ Used1 |= DU.Uses[SR1];
+ Used2 |= DU.Uses[SR2];
if (CanDown && DU.Defs[SR1])
CanDown = false;
if (CanUp && DU.Defs[SR2])
@@ -316,6 +317,45 @@ bool HexagonGenMux::genMuxInBlock(MachineBasicBlock &B) {
// Prefer "down", since this will move the MUX farther away from the
// predicate definition.
MachineBasicBlock::iterator At = CanDown ? Def2 : Def1;
+ if (CanDown) {
+ // If the MUX is placed "down", we need to make sure that there aren't
+ // any kills of the source registers between the two defs.
+ if (Used1 || Used2) {
+ auto ResetKill = [this] (unsigned Reg, MachineInstr &MI) -> bool {
+ if (MachineOperand *Op = MI.findRegisterUseOperand(Reg, true, HRI)) {
+ Op->setIsKill(false);
+ return true;
+ }
+ return false;
+ };
+ bool KilledSR1 = false, KilledSR2 = false;
+ for (MachineInstr &MJ : make_range(std::next(It1), It2)) {
+ if (SR1)
+ KilledSR1 |= ResetKill(SR1, MJ);
+ if (SR2)
+ KilledSR2 |= ResetKill(SR1, MJ);
+ }
+ // If any of the source registers were killed in this range, transfer
+ // the kills to the source operands: they will me "moved" to the
+ // resulting MUX and their parent instructions will be deleted.
+ if (KilledSR1) {
+ assert(Src1->isReg());
+ Src1->setIsKill(true);
+ }
+ if (KilledSR2) {
+ assert(Src2->isReg());
+ Src2->setIsKill(true);
+ }
+ }
+ } else {
+ // If the MUX is placed "up", it shouldn't kill any source registers
+ // that are still used afterwards. We can reset the kill flags directly
+ // on the operands, because the source instructions will be erased.
+ if (Used1 && Src1->isReg())
+ Src1->setIsKill(false);
+ if (Used2 && Src2->isReg())
+ Src2->setIsKill(false);
+ }
ML.push_back(MuxInfo(At, DR, PR, SrcT, SrcF, Def1, Def2));
}
diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index e4434136bf86..e5f49ca77a91 100644
--- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -124,6 +124,7 @@ private:
bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src);
bool isOrEquivalentToAdd(const SDNode *N) const;
bool isAlignedMemNode(const MemSDNode *N) const;
+ bool isSmallStackStore(const StoreSDNode *N) const;
bool isPositiveHalfWord(const SDNode *N) const;
// DAG preprocessing functions.
@@ -1462,6 +1463,20 @@ bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {
return N->getAlignment() >= N->getMemoryVT().getStoreSize();
}
+bool HexagonDAGToDAGISel::isSmallStackStore(const StoreSDNode *N) const {
+ unsigned StackSize = MF->getFrameInfo().estimateStackSize(*MF);
+ switch (N->getMemoryVT().getStoreSize()) {
+ case 1:
+ return StackSize <= 56; // 1*2^6 - 8
+ case 2:
+ return StackSize <= 120; // 2*2^6 - 8
+ case 4:
+ return StackSize <= 248; // 4*2^6 - 8
+ default:
+ return false;
+ }
+}
+
// Return true when the given node fits in a positive half word.
bool HexagonDAGToDAGISel::isPositiveHalfWord(const SDNode *N) const {
if (const ConstantSDNode *CN = dyn_cast<const ConstantSDNode>(N)) {
diff --git a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
index b748b58bc0ae..f82ad6cb3da6 100644
--- a/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
+++ b/lib/Target/Hexagon/HexagonLoopIdiomRecognition.cpp
@@ -1744,7 +1744,8 @@ bool PolynomialMultiplyRecognize::recognize() {
// wide as the target's pmpy instruction.
if (!promoteTypes(LoopB, ExitB))
return false;
- convertShiftsToLeft(LoopB, ExitB, IterCount);
+ if (!convertShiftsToLeft(LoopB, ExitB, IterCount))
+ return false;
cleanupLoopBody(LoopB);
}
diff --git a/lib/Target/Hexagon/HexagonPatterns.td b/lib/Target/Hexagon/HexagonPatterns.td
index f269b74fc447..689419638f54 100644
--- a/lib/Target/Hexagon/HexagonPatterns.td
+++ b/lib/Target/Hexagon/HexagonPatterns.td
@@ -401,6 +401,11 @@ def Aext64: PatFrag<(ops node:$Rs), (i64 (anyext node:$Rs))>;
def Zext64: PatFrag<(ops node:$Rs), (i64 (zext node:$Rs))>;
def Sext64: PatLeaf<(i64 Usxtw:$Rs)>;
+def: Pat<(i32 (trunc (sra (mul Sext64:$Rs, Sext64:$Rt), (i32 32)))),
+ (M2_mpy_up (LoReg Sext64:$Rs), (LoReg Sext64:$Rt))>;
+def: Pat<(i32 (trunc (srl (mul Sext64:$Rs, Sext64:$Rt), (i32 32)))),
+ (M2_mpy_up (LoReg Sext64:$Rs), (LoReg Sext64:$Rt))>;
+
def: Pat<(mul (Aext64 I32:$Rs), (Aext64 I32:$Rt)),
(M2_dpmpyuu_s0 I32:$Rs, I32:$Rt)>;
@@ -1470,16 +1475,22 @@ def i32in8ImmPred: PatLeaf<(i32 imm), [{
return v == (int64_t)(int8_t)v;
}]>;
+class SmallStackStore<PatFrag Store>
+ : PatFrag<(ops node:$Val, node:$Addr), (Store node:$Val, node:$Addr), [{
+ return isSmallStackStore(cast<StoreSDNode>(N));
+}]>;
let AddedComplexity = 40 in {
// Even though the offset is not extendable in the store-immediate, we
// can still generate the fi# in the base address. If the final offset
// is not valid for the instruction, we will replace it with a scratch
// register.
-// def: Storexm_fi_pat <truncstorei8, s32_0ImmPred, ToImmByte, S4_storeirb_io>;
-// def: Storexm_fi_pat <truncstorei16, i16in8ImmPred, ToImmHalf,
-// S4_storeirh_io>;
-// def: Storexm_fi_pat <store, i32in8ImmPred, ToImmWord, S4_storeiri_io>;
+ def: Storexm_fi_pat <SmallStackStore<truncstorei8>, s32_0ImmPred,
+ ToImmByte, S4_storeirb_io>;
+ def: Storexm_fi_pat <SmallStackStore<truncstorei16>, i16in8ImmPred,
+ ToImmHalf, S4_storeirh_io>;
+ def: Storexm_fi_pat <SmallStackStore<store>, i32in8ImmPred,
+ ToImmWord, S4_storeiri_io>;
// defm: Storexm_fi_add_pat <truncstorei8, s32_0ImmPred, u6_0ImmPred, ToImmByte,
// S4_storeirb_io>;
diff --git a/lib/Target/Hexagon/HexagonTargetMachine.cpp b/lib/Target/Hexagon/HexagonTargetMachine.cpp
index c757b6ecdd00..e507a797871f 100644
--- a/lib/Target/Hexagon/HexagonTargetMachine.cpp
+++ b/lib/Target/Hexagon/HexagonTargetMachine.cpp
@@ -111,6 +111,7 @@ namespace llvm {
extern char &HexagonExpandCondsetsID;
void initializeHexagonExpandCondsetsPass(PassRegistry&);
void initializeHexagonLoopIdiomRecognizePass(PassRegistry&);
+ void initializeHexagonGenMuxPass(PassRegistry&);
void initializeHexagonOptAddrModePass(PassRegistry&);
Pass *createHexagonLoopIdiomPass();
@@ -152,8 +153,11 @@ static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
extern "C" void LLVMInitializeHexagonTarget() {
// Register the target.
RegisterTargetMachine<HexagonTargetMachine> X(getTheHexagonTarget());
- initializeHexagonLoopIdiomRecognizePass(*PassRegistry::getPassRegistry());
- initializeHexagonOptAddrModePass(*PassRegistry::getPassRegistry());
+
+ PassRegistry &PR = *PassRegistry::getPassRegistry();
+ initializeHexagonLoopIdiomRecognizePass(PR);
+ initializeHexagonGenMuxPass(PR);
+ initializeHexagonOptAddrModePass(PR);
}
HexagonTargetMachine::HexagonTargetMachine(const Target &T, const Triple &TT,
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index f2193013b7aa..68708dc4f50f 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -364,6 +364,18 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::UDIV, MVT::i64, Expand);
setOperationAction(ISD::UREM, MVT::i64, Expand);
+ if (!(Subtarget.hasDSP() && Subtarget.hasMips32r2())) {
+ setOperationAction(ISD::ADDC, MVT::i32, Expand);
+ setOperationAction(ISD::ADDE, MVT::i32, Expand);
+ }
+
+ setOperationAction(ISD::ADDC, MVT::i64, Expand);
+ setOperationAction(ISD::ADDE, MVT::i64, Expand);
+ setOperationAction(ISD::SUBC, MVT::i32, Expand);
+ setOperationAction(ISD::SUBE, MVT::i32, Expand);
+ setOperationAction(ISD::SUBC, MVT::i64, Expand);
+ setOperationAction(ISD::SUBE, MVT::i64, Expand);
+
// Operations not directly supported by Mips.
setOperationAction(ISD::BR_CC, MVT::f32, Expand);
setOperationAction(ISD::BR_CC, MVT::f64, Expand);
@@ -469,6 +481,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setTargetDAGCombine(ISD::AND);
setTargetDAGCombine(ISD::OR);
setTargetDAGCombine(ISD::ADD);
+ setTargetDAGCombine(ISD::SUB);
setTargetDAGCombine(ISD::AssertZext);
setTargetDAGCombine(ISD::SHL);
@@ -918,14 +931,130 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
}
}
+static SDValue performMADD_MSUBCombine(SDNode *ROOTNode, SelectionDAG &CurDAG,
+ const MipsSubtarget &Subtarget) {
+ // ROOTNode must have a multiplication as an operand for the match to be
+ // successful.
+ if (ROOTNode->getOperand(0).getOpcode() != ISD::MUL &&
+ ROOTNode->getOperand(1).getOpcode() != ISD::MUL)
+ return SDValue();
+
+ // We don't handle vector types here.
+ if (ROOTNode->getValueType(0).isVector())
+ return SDValue();
+
+ // For MIPS64, madd / msub instructions are inefficent to use with 64 bit
+ // arithmetic. E.g.
+ // (add (mul a b) c) =>
+ // let res = (madd (mthi (drotr c 32))x(mtlo c) a b) in
+ // MIPS64: (or (dsll (mfhi res) 32) (dsrl (dsll (mflo res) 32) 32)
+ // or
+ // MIPS64R2: (dins (mflo res) (mfhi res) 32 32)
+ //
+ // The overhead of setting up the Hi/Lo registers and reassembling the
+ // result makes this a dubious optimzation for MIPS64. The core of the
+ // problem is that Hi/Lo contain the upper and lower 32 bits of the
+ // operand and result.
+ //
+ // It requires a chain of 4 add/mul for MIPS64R2 to get better code
+ // density than doing it naively, 5 for MIPS64. Additionally, using
+ // madd/msub on MIPS64 requires the operands actually be 32 bit sign
+ // extended operands, not true 64 bit values.
+ //
+ // FIXME: For the moment, disable this completely for MIPS64.
+ if (Subtarget.hasMips64())
+ return SDValue();
+
+ SDValue Mult = ROOTNode->getOperand(0).getOpcode() == ISD::MUL
+ ? ROOTNode->getOperand(0)
+ : ROOTNode->getOperand(1);
+
+ SDValue AddOperand = ROOTNode->getOperand(0).getOpcode() == ISD::MUL
+ ? ROOTNode->getOperand(1)
+ : ROOTNode->getOperand(0);
+
+ // Transform this to a MADD only if the user of this node is the add.
+ // If there are other users of the mul, this function returns here.
+ if (!Mult.hasOneUse())
+ return SDValue();
+
+ // maddu and madd are unusual instructions in that on MIPS64 bits 63..31
+ // must be in canonical form, i.e. sign extended. For MIPS32, the operands
+ // of the multiply must have 32 or more sign bits, otherwise we cannot
+ // perform this optimization. We have to check this here as we're performing
+ // this optimization pre-legalization.
+ SDValue MultLHS = Mult->getOperand(0);
+ SDValue MultRHS = Mult->getOperand(1);
+ unsigned LHSSB = CurDAG.ComputeNumSignBits(MultLHS);
+ unsigned RHSSB = CurDAG.ComputeNumSignBits(MultRHS);
+
+ if (LHSSB < 32 || RHSSB < 32)
+ return SDValue();
+
+ APInt HighMask =
+ APInt::getHighBitsSet(Mult->getValueType(0).getScalarSizeInBits(), 32);
+ bool IsUnsigned = CurDAG.MaskedValueIsZero(Mult->getOperand(0), HighMask) &&
+ CurDAG.MaskedValueIsZero(Mult->getOperand(1), HighMask) &&
+ CurDAG.MaskedValueIsZero(AddOperand, HighMask);
+
+ // Initialize accumulator.
+ SDLoc DL(ROOTNode);
+ SDValue TopHalf;
+ SDValue BottomHalf;
+ BottomHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand,
+ CurDAG.getIntPtrConstant(0, DL));
+
+ TopHalf = CurDAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, AddOperand,
+ CurDAG.getIntPtrConstant(1, DL));
+ SDValue ACCIn = CurDAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped,
+ BottomHalf,
+ TopHalf);
+
+ // Create MipsMAdd(u) / MipsMSub(u) node.
+ bool IsAdd = ROOTNode->getOpcode() == ISD::ADD;
+ unsigned Opcode = IsAdd ? (IsUnsigned ? MipsISD::MAddu : MipsISD::MAdd)
+ : (IsUnsigned ? MipsISD::MSubu : MipsISD::MSub);
+ SDValue MAddOps[3] = {
+ CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(0)),
+ CurDAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Mult->getOperand(1)), ACCIn};
+ EVT VTs[2] = {MVT::i32, MVT::i32};
+ SDValue MAdd = CurDAG.getNode(Opcode, DL, VTs, MAddOps);
+
+ SDValue ResLo = CurDAG.getNode(MipsISD::MFLO, DL, MVT::i32, MAdd);
+ SDValue ResHi = CurDAG.getNode(MipsISD::MFHI, DL, MVT::i32, MAdd);
+ SDValue Combined =
+ CurDAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, ResLo, ResHi);
+ return Combined;
+}
+
+static SDValue performSUBCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget &Subtarget) {
+ // (sub v0 (mul v1, v2)) => (msub v1, v2, v0)
+ if (DCI.isBeforeLegalizeOps()) {
+ if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() &&
+ !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64)
+ return performMADD_MSUBCombine(N, DAG, Subtarget);
+
+ return SDValue();
+ }
+
+ return SDValue();
+}
+
static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget &Subtarget) {
- // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt))
+ // (add v0 (mul v1, v2)) => (madd v1, v2, v0)
+ if (DCI.isBeforeLegalizeOps()) {
+ if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() &&
+ !Subtarget.inMips16Mode() && N->getValueType(0) == MVT::i64)
+ return performMADD_MSUBCombine(N, DAG, Subtarget);
- if (DCI.isBeforeLegalizeOps())
return SDValue();
+ }
+ // (add v0, (add v1, abs_lo(tjt))) => (add (add v0, v1), abs_lo(tjt))
SDValue Add = N->getOperand(1);
if (Add.getOpcode() != ISD::ADD)
@@ -1053,6 +1182,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return performAssertZextCombine(N, DAG, DCI, Subtarget);
case ISD::SHL:
return performSHLCombine(N, DAG, DCI, Subtarget);
+ case ISD::SUB:
+ return performSUBCombine(N, DAG, DCI, Subtarget);
}
return SDValue();
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index df62c66b75a3..4adf77f8d9a9 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -103,12 +103,9 @@ void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID);
for (unsigned i = 1; i < Cond.size(); ++i) {
- if (Cond[i].isReg())
- MIB.addReg(Cond[i].getReg());
- else if (Cond[i].isImm())
- MIB.addImm(Cond[i].getImm());
- else
- assert(false && "Cannot copy operand");
+ assert((Cond[i].isImm() || Cond[i].isReg()) &&
+ "Cannot copy operand for conditional branch!");
+ MIB.add(Cond[i]);
}
MIB.addMBB(TBB);
}
diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp
index b95f1158fa56..272595af5f6f 100644
--- a/lib/Target/Mips/MipsLongBranch.cpp
+++ b/lib/Target/Mips/MipsLongBranch.cpp
@@ -274,8 +274,8 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
if (IsPIC) {
MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB);
MF->insert(FallThroughMBB, BalTgtMBB);
- LongBrMBB->addSuccessor(BalTgtMBB);
- BalTgtMBB->addSuccessor(TgtMBB);
+ LongBrMBB->addSuccessor(BalTgtMBB, BranchProbability::getOne());
+ BalTgtMBB->addSuccessor(&*FallThroughMBB, BranchProbability::getOne());
// We must select between the MIPS32r6/MIPS64r6 BAL (which is a normal
// instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an
@@ -342,8 +342,8 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
.addReg(Mips::SP).addImm(8);
if (Subtarget.hasMips32r6())
- BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR))
- .addReg(Mips::ZERO).addReg(Mips::AT);
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR), Mips::ZERO)
+ .addReg(Mips::AT);
else
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR)).addReg(Mips::AT);
@@ -415,8 +415,8 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
.addReg(Mips::SP_64).addImm(0);
if (Subtarget.hasMips64r6())
- BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR64))
- .addReg(Mips::ZERO_64).addReg(Mips::AT_64);
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR64), Mips::ZERO_64)
+ .addReg(Mips::AT_64);
else
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64);
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index 49ae6dd4cd39..4be26dd25dc0 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -245,46 +245,64 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
}
}
-void MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
- SDValue CmpLHS, const SDLoc &DL,
- SDNode *Node) const {
- unsigned Opc = InFlag.getOpcode(); (void)Opc;
-
- assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
- (Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
- "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
-
- unsigned SLTuOp = Mips::SLTu, ADDuOp = Mips::ADDu;
- if (Subtarget->isGP64bit()) {
- SLTuOp = Mips::SLTu64;
- ADDuOp = Mips::DADDu;
- }
-
- SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) };
+void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const {
+ SDValue InFlag = Node->getOperand(2);
+ unsigned Opc = InFlag.getOpcode();
SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1);
EVT VT = LHS.getValueType();
- SDNode *Carry = CurDAG->getMachineNode(SLTuOp, DL, VT, Ops);
-
- if (Subtarget->isGP64bit()) {
- // On 64-bit targets, sltu produces an i64 but our backend currently says
- // that SLTu64 produces an i32. We need to fix this in the long run but for
- // now, just make the DAG type-correct by asserting the upper bits are zero.
- Carry = CurDAG->getMachineNode(Mips::SUBREG_TO_REG, DL, VT,
- CurDAG->getTargetConstant(0, DL, VT),
- SDValue(Carry, 0),
- CurDAG->getTargetConstant(Mips::sub_32, DL,
- VT));
+ // In the base case, we can rely on the carry bit from the addsc
+ // instruction.
+ if (Opc == ISD::ADDC) {
+ SDValue Ops[3] = {LHS, RHS, InFlag};
+ CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Ops);
+ return;
}
- // Generate a second addition only if we know that RHS is not a
- // constant-zero node.
- SDNode *AddCarry = Carry;
- ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS);
- if (!C || C->getZExtValue())
- AddCarry = CurDAG->getMachineNode(ADDuOp, DL, VT, SDValue(Carry, 0), RHS);
+ assert(Opc == ISD::ADDE && "ISD::ADDE not in a chain of ADDE nodes!");
+
+ // The more complex case is when there is a chain of ISD::ADDE nodes like:
+ // (adde (adde (adde (addc a b) c) d) e).
+ //
+ // The addwc instruction does not write to the carry bit, instead it writes
+ // to bit 20 of the dsp control register. To match this series of nodes, each
+ // intermediate adde node must be expanded to write the carry bit before the
+ // addition.
+
+ // Start by reading the overflow field for addsc and moving the value to the
+ // carry field. The usage of 1 here with MipsISD::RDDSP / Mips::WRDSP
+ // corresponds to reading/writing the entire control register to/from a GPR.
+
+ SDValue CstOne = CurDAG->getTargetConstant(1, DL, MVT::i32);
+
+ SDValue OuFlag = CurDAG->getTargetConstant(20, DL, MVT::i32);
+
+ SDNode *DSPCtrlField =
+ CurDAG->getMachineNode(Mips::RDDSP, DL, MVT::i32, MVT::Glue, CstOne, InFlag);
+
+ SDNode *Carry = CurDAG->getMachineNode(
+ Mips::EXT, DL, MVT::i32, SDValue(DSPCtrlField, 0), OuFlag, CstOne);
- CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0));
+ SDValue Ops[4] = {SDValue(DSPCtrlField, 0),
+ CurDAG->getTargetConstant(6, DL, MVT::i32), CstOne,
+ SDValue(Carry, 0)};
+ SDNode *DSPCFWithCarry = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, Ops);
+
+ // My reading of the the MIPS DSP 3.01 specification isn't as clear as I
+ // would like about whether bit 20 always gets overwritten by addwc.
+ // Hence take an extremely conservative view and presume it's sticky. We
+ // therefore need to clear it.
+
+ SDValue Zero = CurDAG->getRegister(Mips::ZERO, MVT::i32);
+
+ SDValue InsOps[4] = {Zero, OuFlag, CstOne, SDValue(DSPCFWithCarry, 0)};
+ SDNode *DSPCtrlFinal = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, InsOps);
+
+ SDNode *WrDSP = CurDAG->getMachineNode(Mips::WRDSP, DL, MVT::Glue,
+ SDValue(DSPCtrlFinal, 0), CstOne);
+
+ SDValue Operands[3] = {LHS, RHS, SDValue(WrDSP, 0)};
+ CurDAG->SelectNodeTo(Node, Mips::ADDWC, VT, MVT::Glue, Operands);
}
/// Match frameindex
@@ -765,19 +783,8 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) {
switch(Opcode) {
default: break;
- case ISD::SUBE: {
- SDValue InFlag = Node->getOperand(2);
- unsigned Opc = Subtarget->isGP64bit() ? Mips::DSUBu : Mips::SUBu;
- selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node);
- return true;
- }
-
case ISD::ADDE: {
- if (Subtarget->hasDSP()) // Select DSP instructions, ADDSC and ADDWC.
- break;
- SDValue InFlag = Node->getOperand(2);
- unsigned Opc = Subtarget->isGP64bit() ? Mips::DADDu : Mips::ADDu;
- selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node);
+ selectAddE(Node, DL);
return true;
}
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h
index f89a350cab04..6f38289c5a45 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.h
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h
@@ -41,8 +41,7 @@ private:
const SDLoc &dl, EVT Ty, bool HasLo,
bool HasHi);
- void selectAddESubE(unsigned MOp, SDValue InFlag, SDValue CmpLHS,
- const SDLoc &DL, SDNode *Node) const;
+ void selectAddE(SDNode *Node, const SDLoc &DL) const;
bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const;
bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset,
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp
index bf7f079e3105..2382ea271661 100644
--- a/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -179,8 +179,6 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::LOAD, MVT::i32, Custom);
setOperationAction(ISD::STORE, MVT::i32, Custom);
- setTargetDAGCombine(ISD::ADDE);
- setTargetDAGCombine(ISD::SUBE);
setTargetDAGCombine(ISD::MUL);
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
@@ -421,163 +419,6 @@ SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
return MipsTargetLowering::LowerOperation(Op, DAG);
}
-// selectMADD -
-// Transforms a subgraph in CurDAG if the following pattern is found:
-// (addc multLo, Lo0), (adde multHi, Hi0),
-// where,
-// multHi/Lo: product of multiplication
-// Lo0: initial value of Lo register
-// Hi0: initial value of Hi register
-// Return true if pattern matching was successful.
-static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
- // ADDENode's second operand must be a flag output of an ADDC node in order
- // for the matching to be successful.
- SDNode *ADDCNode = ADDENode->getOperand(2).getNode();
-
- if (ADDCNode->getOpcode() != ISD::ADDC)
- return false;
-
- SDValue MultHi = ADDENode->getOperand(0);
- SDValue MultLo = ADDCNode->getOperand(0);
- SDNode *MultNode = MultHi.getNode();
- unsigned MultOpc = MultHi.getOpcode();
-
- // MultHi and MultLo must be generated by the same node,
- if (MultLo.getNode() != MultNode)
- return false;
-
- // and it must be a multiplication.
- if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
- return false;
-
- // MultLo amd MultHi must be the first and second output of MultNode
- // respectively.
- if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
- return false;
-
- // Transform this to a MADD only if ADDENode and ADDCNode are the only users
- // of the values of MultNode, in which case MultNode will be removed in later
- // phases.
- // If there exist users other than ADDENode or ADDCNode, this function returns
- // here, which will result in MultNode being mapped to a single MULT
- // instruction node rather than a pair of MULT and MADD instructions being
- // produced.
- if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
- return false;
-
- SDLoc DL(ADDENode);
-
- // Initialize accumulator.
- SDValue ACCIn = CurDAG->getNode(MipsISD::MTLOHI, DL, MVT::Untyped,
- ADDCNode->getOperand(1),
- ADDENode->getOperand(1));
-
- // create MipsMAdd(u) node
- MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
-
- SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped,
- MultNode->getOperand(0),// Factor 0
- MultNode->getOperand(1),// Factor 1
- ACCIn);
-
- // replace uses of adde and addc here
- if (!SDValue(ADDCNode, 0).use_empty()) {
- SDValue LoOut = CurDAG->getNode(MipsISD::MFLO, DL, MVT::i32, MAdd);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
- }
- if (!SDValue(ADDENode, 0).use_empty()) {
- SDValue HiOut = CurDAG->getNode(MipsISD::MFHI, DL, MVT::i32, MAdd);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
- }
-
- return true;
-}
-
-// selectMSUB -
-// Transforms a subgraph in CurDAG if the following pattern is found:
-// (addc Lo0, multLo), (sube Hi0, multHi),
-// where,
-// multHi/Lo: product of multiplication
-// Lo0: initial value of Lo register
-// Hi0: initial value of Hi register
-// Return true if pattern matching was successful.
-static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
- // SUBENode's second operand must be a flag output of an SUBC node in order
- // for the matching to be successful.
- SDNode *SUBCNode = SUBENode->getOperand(2).getNode();
-
- if (SUBCNode->getOpcode() != ISD::SUBC)
- return false;
-
- SDValue MultHi = SUBENode->getOperand(1);
- SDValue MultLo = SUBCNode->getOperand(1);
- SDNode *MultNode = MultHi.getNode();
- unsigned MultOpc = MultHi.getOpcode();
-
- // MultHi and MultLo must be generated by the same node,
- if (MultLo.getNode() != MultNode)
- return false;
-
- // and it must be a multiplication.
- if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
- return false;
-
- // MultLo amd MultHi must be the first and second output of MultNode
- // respectively.
- if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
- return false;
-
- // Transform this to a MSUB only if SUBENode and SUBCNode are the only users
- // of the values of MultNode, in which case MultNode will be removed in later
- // phases.
- // If there exist users other than SUBENode or SUBCNode, this function returns
- // here, which will result in MultNode being mapped to a single MULT
- // instruction node rather than a pair of MULT and MSUB instructions being
- // produced.
- if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
- return false;
-
- SDLoc DL(SUBENode);
-
- // Initialize accumulator.
- SDValue ACCIn = CurDAG->getNode(MipsISD::MTLOHI, DL, MVT::Untyped,
- SUBCNode->getOperand(0),
- SUBENode->getOperand(0));
-
- // create MipsSub(u) node
- MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
-
- SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
- MultNode->getOperand(0),// Factor 0
- MultNode->getOperand(1),// Factor 1
- ACCIn);
-
- // replace uses of sube and subc here
- if (!SDValue(SUBCNode, 0).use_empty()) {
- SDValue LoOut = CurDAG->getNode(MipsISD::MFLO, DL, MVT::i32, MSub);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
- }
- if (!SDValue(SUBENode, 0).use_empty()) {
- SDValue HiOut = CurDAG->getNode(MipsISD::MFHI, DL, MVT::i32, MSub);
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
- }
-
- return true;
-}
-
-static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI,
- const MipsSubtarget &Subtarget) {
- if (DCI.isBeforeLegalize())
- return SDValue();
-
- if (Subtarget.hasMips32() && !Subtarget.hasMips32r6() &&
- N->getValueType(0) == MVT::i32 && selectMADD(N, &DAG))
- return SDValue(N, 0);
-
- return SDValue();
-}
-
// Fold zero extensions into MipsISD::VEXTRACT_[SZ]EXT_ELT
//
// Performs the following transformations:
@@ -820,19 +661,6 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
-static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI,
- const MipsSubtarget &Subtarget) {
- if (DCI.isBeforeLegalize())
- return SDValue();
-
- if (Subtarget.hasMips32() && N->getValueType(0) == MVT::i32 &&
- selectMSUB(N, &DAG))
- return SDValue(N, 0);
-
- return SDValue();
-}
-
static SDValue genConstMult(SDValue X, uint64_t C, const SDLoc &DL, EVT VT,
EVT ShiftTy, SelectionDAG &DAG) {
// Clear the upper (64 - VT.sizeInBits) bits.
@@ -1110,16 +938,12 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
SDValue Val;
switch (N->getOpcode()) {
- case ISD::ADDE:
- return performADDECombine(N, DAG, DCI, Subtarget);
case ISD::AND:
Val = performANDCombine(N, DAG, DCI, Subtarget);
break;
case ISD::OR:
Val = performORCombine(N, DAG, DCI, Subtarget);
break;
- case ISD::SUBE:
- return performSUBECombine(N, DAG, DCI, Subtarget);
case ISD::MUL:
return performMULCombine(N, DAG, DCI, this);
case ISD::SHL:
diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h
index 625a652a0ca0..ccd47f00c0d3 100644
--- a/lib/Target/Mips/MipsSubtarget.h
+++ b/lib/Target/Mips/MipsSubtarget.h
@@ -78,7 +78,7 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
// IsNan2008 - IEEE 754-2008 NaN encoding.
bool IsNaN2008bit;
- // IsFP64bit - General-purpose registers are 64 bits wide
+ // IsGP64bit - General-purpose registers are 64 bits wide
bool IsGP64bit;
// IsPTR64bit - Pointers are 64 bit wide
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 28d496ee9ca1..afd2e87078a9 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -2907,19 +2907,6 @@ SDValue PPCDAGToDAGISel::get64BitZExtCompare(SDValue LHS, SDValue RHS,
getI64Imm(58, dl), getI64Imm(63, dl)),
0);
}
- case ISD::SETNE: {
- // {addc.reg, addc.CA} = (addcarry (xor %a, %b), -1)
- // (zext (setcc %a, %b, setne)) -> (sube addc.reg, addc.reg, addc.CA)
- // {addcz.reg, addcz.CA} = (addcarry %a, -1)
- // (zext (setcc %a, 0, setne)) -> (sube addcz.reg, addcz.reg, addcz.CA)
- SDValue Xor = IsRHSZero ? LHS :
- SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
- SDValue AC =
- SDValue(CurDAG->getMachineNode(PPC::ADDIC8, dl, MVT::i64, MVT::Glue,
- Xor, getI32Imm(~0U, dl)), 0);
- return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, AC,
- Xor, AC.getValue(1)), 0);
- }
}
}
@@ -2944,19 +2931,6 @@ SDValue PPCDAGToDAGISel::get64BitSExtCompare(SDValue LHS, SDValue RHS,
return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, Addic,
Addic, Addic.getValue(1)), 0);
}
- case ISD::SETNE: {
- // {subfc.reg, subfc.CA} = (subcarry 0, (xor %a, %b))
- // (sext (setcc %a, %b, setne)) -> (sube subfc.reg, subfc.reg, subfc.CA)
- // {subfcz.reg, subfcz.CA} = (subcarry 0, %a)
- // (sext (setcc %a, 0, setne)) -> (sube subfcz.reg, subfcz.reg, subfcz.CA)
- SDValue Xor = IsRHSZero ? LHS :
- SDValue(CurDAG->getMachineNode(PPC::XOR8, dl, MVT::i64, LHS, RHS), 0);
- SDValue SC =
- SDValue(CurDAG->getMachineNode(PPC::SUBFIC8, dl, MVT::i64, MVT::Glue,
- Xor, getI32Imm(0, dl)), 0);
- return SDValue(CurDAG->getMachineNode(PPC::SUBFE8, dl, MVT::i64, SC,
- SC, SC.getValue(1)), 0);
- }
}
}
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index bda4e5e81734..662550f7a396 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -136,7 +136,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
addRegisterClass(MVT::f64, &PPC::F8RCRegClass);
}
- // PowerPC has an i16 but no i8 (or i1) SEXTLOAD
+ // PowerPC has an i16 but no i8 (or i1) SEXTLOAD.
for (MVT VT : MVT::integer_valuetypes()) {
setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand);
@@ -175,7 +175,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setOperationAction(ISD::UINT_TO_FP, MVT::i1, Custom);
}
- // PowerPC does not support direct load / store of condition registers
+ // PowerPC does not support direct load/store of condition registers.
setOperationAction(ISD::LOAD, MVT::i1, Custom);
setOperationAction(ISD::STORE, MVT::i1, Custom);
@@ -204,11 +204,23 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
setOperationAction(ISD::FNEARBYINT, MVT::ppcf128, Expand);
setOperationAction(ISD::FREM, MVT::ppcf128, Expand);
- // PowerPC has no SREM/UREM instructions
- setOperationAction(ISD::SREM, MVT::i32, Expand);
- setOperationAction(ISD::UREM, MVT::i32, Expand);
- setOperationAction(ISD::SREM, MVT::i64, Expand);
- setOperationAction(ISD::UREM, MVT::i64, Expand);
+ // PowerPC has no SREM/UREM instructions unless we are on P9
+ // On P9 we may use a hardware instruction to compute the remainder.
+ // The instructions are not legalized directly because in the cases where the
+ // result of both the remainder and the division is required it is more
+ // efficient to compute the remainder from the result of the division rather
+ // than use the remainder instruction.
+ if (Subtarget.isISA3_0()) {
+ setOperationAction(ISD::SREM, MVT::i32, Custom);
+ setOperationAction(ISD::UREM, MVT::i32, Custom);
+ setOperationAction(ISD::SREM, MVT::i64, Custom);
+ setOperationAction(ISD::UREM, MVT::i64, Custom);
+ } else {
+ setOperationAction(ISD::SREM, MVT::i32, Expand);
+ setOperationAction(ISD::UREM, MVT::i32, Expand);
+ setOperationAction(ISD::SREM, MVT::i64, Expand);
+ setOperationAction(ISD::UREM, MVT::i64, Expand);
+ }
// Don't use SMUL_LOHI/UMUL_LOHI or SDIVREM/UDIVREM to lower SREM/UREM.
setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
@@ -1116,6 +1128,7 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
case PPCISD::VPERM: return "PPCISD::VPERM";
case PPCISD::XXSPLT: return "PPCISD::XXSPLT";
case PPCISD::XXINSERT: return "PPCISD::XXINSERT";
+ case PPCISD::XXREVERSE: return "PPCISD::XXREVERSE";
case PPCISD::XXPERMDI: return "PPCISD::XXPERMDI";
case PPCISD::VECSHL: return "PPCISD::VECSHL";
case PPCISD::CMPB: return "PPCISD::CMPB";
@@ -1598,22 +1611,34 @@ bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) {
return true;
}
-// Check that the mask is shuffling N byte elements.
-static bool isNByteElemShuffleMask(ShuffleVectorSDNode *N, unsigned Width) {
+/// Check that the mask is shuffling N byte elements. Within each N byte
+/// element of the mask, the indices could be either in increasing or
+/// decreasing order as long as they are consecutive.
+/// \param[in] N the shuffle vector SD Node to analyze
+/// \param[in] Width the element width in bytes, could be 2/4/8/16 (HalfWord/
+/// Word/DoubleWord/QuadWord).
+/// \param[in] StepLen the delta indices number among the N byte element, if
+/// the mask is in increasing/decreasing order then it is 1/-1.
+/// \return true iff the mask is shuffling N byte elements.
+static bool isNByteElemShuffleMask(ShuffleVectorSDNode *N, unsigned Width,
+ int StepLen) {
assert((Width == 2 || Width == 4 || Width == 8 || Width == 16) &&
"Unexpected element width.");
+ assert((StepLen == 1 || StepLen == -1) && "Unexpected element width.");
unsigned NumOfElem = 16 / Width;
unsigned MaskVal[16]; // Width is never greater than 16
for (unsigned i = 0; i < NumOfElem; ++i) {
MaskVal[0] = N->getMaskElt(i * Width);
- if (MaskVal[0] % Width) {
+ if ((StepLen == 1) && (MaskVal[0] % Width)) {
+ return false;
+ } else if ((StepLen == -1) && ((MaskVal[0] + 1) % Width)) {
return false;
}
for (unsigned int j = 1; j < Width; ++j) {
MaskVal[j] = N->getMaskElt(i * Width + j);
- if (MaskVal[j] != MaskVal[j-1] + 1) {
+ if (MaskVal[j] != MaskVal[j-1] + StepLen) {
return false;
}
}
@@ -1624,7 +1649,7 @@ static bool isNByteElemShuffleMask(ShuffleVectorSDNode *N, unsigned Width) {
bool PPC::isXXINSERTWMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
unsigned &InsertAtByte, bool &Swap, bool IsLE) {
- if (!isNByteElemShuffleMask(N, 4))
+ if (!isNByteElemShuffleMask(N, 4, 1))
return false;
// Now we look at mask elements 0,4,8,12
@@ -1701,7 +1726,7 @@ bool PPC::isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
bool &Swap, bool IsLE) {
assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8");
// Ensure each byte index of the word is consecutive.
- if (!isNByteElemShuffleMask(N, 4))
+ if (!isNByteElemShuffleMask(N, 4, 1))
return false;
// Now we look at mask elements 0,4,8,12, which are the beginning of words.
@@ -1759,6 +1784,35 @@ bool PPC::isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
}
}
+bool static isXXBRShuffleMaskHelper(ShuffleVectorSDNode *N, int Width) {
+ assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8");
+
+ if (!isNByteElemShuffleMask(N, Width, -1))
+ return false;
+
+ for (int i = 0; i < 16; i += Width)
+ if (N->getMaskElt(i) != i + Width - 1)
+ return false;
+
+ return true;
+}
+
+bool PPC::isXXBRHShuffleMask(ShuffleVectorSDNode *N) {
+ return isXXBRShuffleMaskHelper(N, 2);
+}
+
+bool PPC::isXXBRWShuffleMask(ShuffleVectorSDNode *N) {
+ return isXXBRShuffleMaskHelper(N, 4);
+}
+
+bool PPC::isXXBRDShuffleMask(ShuffleVectorSDNode *N) {
+ return isXXBRShuffleMaskHelper(N, 8);
+}
+
+bool PPC::isXXBRQShuffleMask(ShuffleVectorSDNode *N) {
+ return isXXBRShuffleMaskHelper(N, 16);
+}
+
/// Can node \p N be lowered to an XXPERMDI instruction? If so, set \p Swap
/// if the inputs to the instruction should be swapped and set \p DM to the
/// value for the immediate.
@@ -1772,7 +1826,7 @@ bool PPC::isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &DM,
assert(N->getValueType(0) == MVT::v16i8 && "Shuffle vector expects v16i8");
// Ensure each byte index of the double word is consecutive.
- if (!isNByteElemShuffleMask(N, 8))
+ if (!isNByteElemShuffleMask(N, 8, 1))
return false;
unsigned M0 = N->getMaskElt(0) / 8;
@@ -6819,6 +6873,7 @@ bool PPCTargetLowering::canReuseLoadAddress(SDValue Op, EVT MemVT,
// Given the head of the old chain, ResChain, insert a token factor containing
// it and NewResChain, and make users of ResChain now be users of that token
// factor.
+// TODO: Remove and use DAG::makeEquivalentMemoryOrdering() instead.
void PPCTargetLowering::spliceIntoChain(SDValue ResChain,
SDValue NewResChain,
SelectionDAG &DAG) const {
@@ -7846,6 +7901,26 @@ SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, PermDI);
}
+ if (Subtarget.hasP9Vector()) {
+ if (PPC::isXXBRHShuffleMask(SVOp)) {
+ SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v8i16, V1);
+ SDValue ReveHWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v8i16, Conv);
+ return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveHWord);
+ } else if (PPC::isXXBRWShuffleMask(SVOp)) {
+ SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v4i32, V1);
+ SDValue ReveWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v4i32, Conv);
+ return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveWord);
+ } else if (PPC::isXXBRDShuffleMask(SVOp)) {
+ SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v2i64, V1);
+ SDValue ReveDWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v2i64, Conv);
+ return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveDWord);
+ } else if (PPC::isXXBRQShuffleMask(SVOp)) {
+ SDValue Conv = DAG.getNode(ISD::BITCAST, dl, MVT::v1i128, V1);
+ SDValue ReveQWord = DAG.getNode(PPCISD::XXREVERSE, dl, MVT::v1i128, Conv);
+ return DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, ReveQWord);
+ }
+ }
+
if (Subtarget.hasVSX()) {
if (V2.isUndef() && PPC::isSplatShuffleMask(SVOp, 4)) {
int SplatIdx = PPC::getVSPLTImmediate(SVOp, 4, DAG);
@@ -8393,6 +8468,18 @@ SDValue PPCTargetLowering::LowerINTRINSIC_VOID(SDValue Op,
return SDValue();
}
+SDValue PPCTargetLowering::LowerREM(SDValue Op, SelectionDAG &DAG) const {
+ // Check for a DIV with the same operands as this REM.
+ for (auto UI : Op.getOperand(1)->uses()) {
+ if ((Op.getOpcode() == ISD::SREM && UI->getOpcode() == ISD::SDIV) ||
+ (Op.getOpcode() == ISD::UREM && UI->getOpcode() == ISD::UDIV))
+ if (UI->getOperand(0) == Op.getOperand(0) &&
+ UI->getOperand(1) == Op.getOperand(1))
+ return SDValue();
+ }
+ return Op;
+}
+
SDValue PPCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
SelectionDAG &DAG) const {
SDLoc dl(Op);
@@ -8861,6 +8948,9 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::INTRINSIC_VOID:
return LowerINTRINSIC_VOID(Op, DAG);
+ case ISD::SREM:
+ case ISD::UREM:
+ return LowerREM(Op, DAG);
}
}
diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h
index 7982a4a9e9fb..a5108727bb4b 100644
--- a/lib/Target/PowerPC/PPCISelLowering.h
+++ b/lib/Target/PowerPC/PPCISelLowering.h
@@ -86,6 +86,10 @@ namespace llvm {
///
XXINSERT,
+ /// XXREVERSE - The PPC VSX reverse instruction
+ ///
+ XXREVERSE,
+
/// VECSHL - The PPC VSX shift left instruction
///
VECSHL,
@@ -458,6 +462,23 @@ namespace llvm {
/// for a XXSLDWI instruction.
bool isXXSLDWIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
bool &Swap, bool IsLE);
+
+ /// isXXBRHShuffleMask - Return true if this is a shuffle mask suitable
+ /// for a XXBRH instruction.
+ bool isXXBRHShuffleMask(ShuffleVectorSDNode *N);
+
+ /// isXXBRWShuffleMask - Return true if this is a shuffle mask suitable
+ /// for a XXBRW instruction.
+ bool isXXBRWShuffleMask(ShuffleVectorSDNode *N);
+
+ /// isXXBRDShuffleMask - Return true if this is a shuffle mask suitable
+ /// for a XXBRD instruction.
+ bool isXXBRDShuffleMask(ShuffleVectorSDNode *N);
+
+ /// isXXBRQShuffleMask - Return true if this is a shuffle mask suitable
+ /// for a XXBRQ instruction.
+ bool isXXBRQShuffleMask(ShuffleVectorSDNode *N);
+
/// isXXPERMDIShuffleMask - Return true if this is a shuffle mask suitable
/// for a XXPERMDI instruction.
bool isXXPERMDIShuffleMask(ShuffleVectorSDNode *N, unsigned &ShiftElts,
@@ -918,6 +939,7 @@ namespace llvm {
SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerREM(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSCALAR_TO_VECTOR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td
index 295590b2acf6..70536a6039b8 100644
--- a/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -683,6 +683,16 @@ def DIVDE : XOForm_1<31, 425, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB),
"divde $rT, $rA, $rB", IIC_IntDivD,
[(set i64:$rT, (int_ppc_divde g8rc:$rA, g8rc:$rB))]>,
isPPC64, Requires<[HasExtDiv]>;
+
+let Predicates = [IsISA3_0] in {
+def MODSD : XForm_8<31, 777, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB),
+ "modsd $rT, $rA, $rB", IIC_IntDivW,
+ [(set i64:$rT, (srem i64:$rA, i64:$rB))]>;
+def MODUD : XForm_8<31, 265, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB),
+ "modud $rT, $rA, $rB", IIC_IntDivW,
+ [(set i64:$rT, (urem i64:$rA, i64:$rB))]>;
+}
+
let Defs = [CR0] in
def DIVDEo : XOForm_1<31, 425, 0, (outs g8rc:$rT), (ins g8rc:$rA, g8rc:$rB),
"divde. $rT, $rA, $rB", IIC_IntDivD,
diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp
index f3c68c443b1b..236e513bec23 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -1964,7 +1964,7 @@ bool PPCInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
}
case PPC::CFENCE8: {
auto Val = MI.getOperand(0).getReg();
- BuildMI(MBB, MI, DL, get(PPC::CMPW), PPC::CR7).addReg(Val).addReg(Val);
+ BuildMI(MBB, MI, DL, get(PPC::CMPD), PPC::CR7).addReg(Val).addReg(Val);
BuildMI(MBB, MI, DL, get(PPC::CTRL_DEP))
.addImm(PPC::PRED_NE_MINUS)
.addReg(PPC::CR7)
diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td
index 8223aa655e38..47d59c25392a 100644
--- a/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/lib/Target/PowerPC/PPCInstrInfo.td
@@ -53,6 +53,10 @@ def SDT_PPCVecInsert : SDTypeProfile<1, 3, [ SDTCisVec<0>,
SDTCisVec<1>, SDTCisVec<2>, SDTCisInt<3>
]>;
+def SDT_PPCVecReverse: SDTypeProfile<1, 1, [ SDTCisVec<0>,
+ SDTCisVec<1>
+]>;
+
def SDT_PPCxxpermdi: SDTypeProfile<1, 3, [ SDTCisVec<0>,
SDTCisVec<1>, SDTCisVec<2>, SDTCisInt<3>
]>;
@@ -174,6 +178,7 @@ def PPCaddiDtprelL : SDNode<"PPCISD::ADDI_DTPREL_L", SDTIntBinOp>;
def PPCvperm : SDNode<"PPCISD::VPERM", SDT_PPCvperm, []>;
def PPCxxsplt : SDNode<"PPCISD::XXSPLT", SDT_PPCVecSplat, []>;
def PPCxxinsert : SDNode<"PPCISD::XXINSERT", SDT_PPCVecInsert, []>;
+def PPCxxreverse : SDNode<"PPCISD::XXREVERSE", SDT_PPCVecReverse, []>;
def PPCxxpermdi : SDNode<"PPCISD::XXPERMDI", SDT_PPCxxpermdi, []>;
def PPCvecshl : SDNode<"PPCISD::VECSHL", SDT_PPCVecShift, []>;
@@ -2544,6 +2549,14 @@ let Uses = [RM] in {
"mffs. $rT", IIC_IntMFFS, []>, isDOT;
}
+let Predicates = [IsISA3_0] in {
+def MODSW : XForm_8<31, 779, (outs gprc:$rT), (ins gprc:$rA, gprc:$rB),
+ "modsw $rT, $rA, $rB", IIC_IntDivW,
+ [(set i32:$rT, (srem i32:$rA, i32:$rB))]>;
+def MODUW : XForm_8<31, 267, (outs gprc:$rT), (ins gprc:$rA, gprc:$rB),
+ "moduw $rT, $rA, $rB", IIC_IntDivW,
+ [(set i32:$rT, (urem i32:$rA, i32:$rB))]>;
+}
let PPC970_Unit = 1, hasSideEffects = 0 in { // FXU Operations.
// XO-Form instructions. Arithmetic instructions that can set overflow bit
diff --git a/lib/Target/PowerPC/PPCInstrVSX.td b/lib/Target/PowerPC/PPCInstrVSX.td
index e214d26c063b..9cfc897cdb3f 100644
--- a/lib/Target/PowerPC/PPCInstrVSX.td
+++ b/lib/Target/PowerPC/PPCInstrVSX.td
@@ -2340,6 +2340,16 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in {
def XXBRD : XX2_XT6_XO5_XB6<60, 23, 475, "xxbrd", vsrc, []>;
def XXBRQ : XX2_XT6_XO5_XB6<60, 31, 475, "xxbrq", vsrc, []>;
+ // Vector Reverse
+ def : Pat<(v8i16 (PPCxxreverse v8i16 :$A)),
+ (v8i16 (COPY_TO_REGCLASS (XXBRH (COPY_TO_REGCLASS $A, VSRC)), VRRC))>;
+ def : Pat<(v4i32 (PPCxxreverse v4i32 :$A)),
+ (v4i32 (XXBRW $A))>;
+ def : Pat<(v2i64 (PPCxxreverse v2i64 :$A)),
+ (v2i64 (XXBRD $A))>;
+ def : Pat<(v1i128 (PPCxxreverse v1i128 :$A)),
+ (v1i128 (COPY_TO_REGCLASS (XXBRQ (COPY_TO_REGCLASS $A, VSRC)), VRRC))>;
+
// Vector Permute
def XXPERM : XX3_XT5_XA5_XB5<60, 26, "xxperm" , vsrc, vsrc, vsrc,
IIC_VecPerm, []>;
diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp
index aad913924692..637e52bbdbee 100644
--- a/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -273,6 +273,20 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
return Reserved;
}
+bool PPCRegisterInfo::isCallerPreservedPhysReg(unsigned PhysReg,
+ const MachineFunction &MF) const {
+ assert(TargetRegisterInfo::isPhysicalRegister(PhysReg));
+ if (TM.isELFv2ABI() && PhysReg == PPC::X2) {
+ // X2 is guaranteed to be preserved within a function if it is reserved.
+ // The reason it's reserved is that it's the TOC pointer (and the function
+ // uses the TOC). In functions where it isn't reserved (i.e. leaf functions
+ // with no TOC access), we can't claim that it is preserved.
+ return (getReservedRegs(MF).test(PPC::X2));
+ } else {
+ return false;
+ }
+}
+
unsigned PPCRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
MachineFunction &MF) const {
const PPCFrameLowering *TFI = getFrameLowering(MF);
diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h
index 4a96327fe552..0bbb71fdf9fb 100644
--- a/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -83,6 +83,7 @@ public:
void adjustStackMapLiveOutMask(uint32_t *Mask) const override;
BitVector getReservedRegs(const MachineFunction &MF) const override;
+ bool isCallerPreservedPhysReg(unsigned PhysReg, const MachineFunction &MF) const override;
/// We require the register scavenger.
bool requiresRegisterScavenging(const MachineFunction &MF) const override {
diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
index 5559cdc5fe46..3dbd5f5b9a92 100644
--- a/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
+++ b/lib/Target/PowerPC/PPCTargetTransformInfo.cpp
@@ -230,7 +230,7 @@ unsigned PPCTTIImpl::getNumberOfRegisters(bool Vector) {
return ST->hasVSX() ? 64 : 32;
}
-unsigned PPCTTIImpl::getRegisterBitWidth(bool Vector) {
+unsigned PPCTTIImpl::getRegisterBitWidth(bool Vector) const {
if (Vector) {
if (ST->hasQPX()) return 256;
if (ST->hasAltivec()) return 128;
diff --git a/lib/Target/PowerPC/PPCTargetTransformInfo.h b/lib/Target/PowerPC/PPCTargetTransformInfo.h
index 2e0116fee04c..758c335def08 100644
--- a/lib/Target/PowerPC/PPCTargetTransformInfo.h
+++ b/lib/Target/PowerPC/PPCTargetTransformInfo.h
@@ -63,7 +63,7 @@ public:
bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize);
bool enableInterleavedAccessVectorization();
unsigned getNumberOfRegisters(bool Vector);
- unsigned getRegisterBitWidth(bool Vector);
+ unsigned getRegisterBitWidth(bool Vector) const;
unsigned getCacheLineSize();
unsigned getPrefetchDistance();
unsigned getMaxInterleaveFactor(unsigned VF);
diff --git a/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp b/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp
index 6a3dc6799c43..422c16b8eb62 100644
--- a/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp
+++ b/lib/Target/SystemZ/SystemZTargetTransformInfo.cpp
@@ -302,7 +302,7 @@ unsigned SystemZTTIImpl::getNumberOfRegisters(bool Vector) {
return 0;
}
-unsigned SystemZTTIImpl::getRegisterBitWidth(bool Vector) {
+unsigned SystemZTTIImpl::getRegisterBitWidth(bool Vector) const {
if (!Vector)
return 64;
if (ST->hasVector())
diff --git a/lib/Target/SystemZ/SystemZTargetTransformInfo.h b/lib/Target/SystemZ/SystemZTargetTransformInfo.h
index ad597f5c65f0..bdba7601eb78 100644
--- a/lib/Target/SystemZ/SystemZTargetTransformInfo.h
+++ b/lib/Target/SystemZ/SystemZTargetTransformInfo.h
@@ -53,7 +53,7 @@ public:
/// @{
unsigned getNumberOfRegisters(bool Vector);
- unsigned getRegisterBitWidth(bool Vector);
+ unsigned getRegisterBitWidth(bool Vector) const;
bool prefersVectorizedAddressing() { return false; }
bool supportsEfficientVectorElementLoadStore() { return true; }
diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
index ddf964e7dbb7..5ad147e5e596 100644
--- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
+++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
@@ -46,9 +46,7 @@ public:
/// .functype
virtual void emitIndirectFunctionType(StringRef name,
SmallVectorImpl<MVT> &Params,
- SmallVectorImpl<MVT> &Results) {
- llvm_unreachable("emitIndirectFunctionType not implemented");
- }
+ SmallVectorImpl<MVT> &Results) = 0;
/// .indidx
virtual void emitIndIdx(const MCExpr *Value) = 0;
/// .import_global
diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
index 27c01cb8acf7..19e14f3261aa 100644
--- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
+++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp
@@ -16,11 +16,15 @@
#include "MCTargetDesc/WebAssemblyFixupKinds.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCFixup.h"
+#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCSymbolWasm.h"
#include "llvm/MC/MCWasmObjectWriter.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
+
using namespace llvm;
namespace {
@@ -29,8 +33,8 @@ public:
explicit WebAssemblyWasmObjectWriter(bool Is64Bit);
private:
- unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
- const MCFixup &Fixup, bool IsPCRel) const override;
+ unsigned getRelocType(const MCValue &Target,
+ const MCFixup &Fixup) const override;
};
} // end anonymous namespace
@@ -39,16 +43,13 @@ WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit)
// Test whether the given expression computes a function address.
static bool IsFunctionExpr(const MCExpr *Expr) {
- if (const MCSymbolRefExpr *SyExp =
- dyn_cast<MCSymbolRefExpr>(Expr))
+ if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr))
return cast<MCSymbolWasm>(SyExp->getSymbol()).isFunction();
- if (const MCBinaryExpr *BinOp =
- dyn_cast<MCBinaryExpr>(Expr))
+ if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr))
return IsFunctionExpr(BinOp->getLHS()) != IsFunctionExpr(BinOp->getRHS());
- if (const MCUnaryExpr *UnOp =
- dyn_cast<MCUnaryExpr>(Expr))
+ if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))
return IsFunctionExpr(UnOp->getSubExpr());
return false;
@@ -59,15 +60,13 @@ static bool IsFunctionType(const MCValue &Target) {
return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX;
}
-unsigned WebAssemblyWasmObjectWriter::getRelocType(MCContext &Ctx,
- const MCValue &Target,
- const MCFixup &Fixup,
- bool IsPCRel) const {
+unsigned
+WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
+ const MCFixup &Fixup) const {
// WebAssembly functions are not allocated in the data address space. To
// resolve a pointer to a function, we must use a special relocation type.
bool IsFunction = IsFunctionExpr(Fixup.getValue());
- assert(!IsPCRel);
switch (unsigned(Fixup.getKind())) {
case WebAssembly::fixup_code_sleb128_i32:
if (IsFunction)
diff --git a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 4178ec0b28f0..b999091e2d29 100644
--- a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -33,6 +33,8 @@
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
@@ -218,9 +220,13 @@ void WebAssemblyAsmPrinter::EmitInstruction(const MachineInstr *MI) {
const MCExpr *WebAssemblyAsmPrinter::lowerConstant(const Constant *CV) {
if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
- if (GV->getValueType()->isFunctionTy())
+ if (GV->getValueType()->isFunctionTy()) {
+ MCSymbol* Sym = getSymbol(GV);
+ if (!isa<MCSymbolELF>(Sym))
+ cast<MCSymbolWasm>(Sym)->setIsFunction(true);
return MCSymbolRefExpr::create(
- getSymbol(GV), MCSymbolRefExpr::VK_WebAssembly_FUNCTION, OutContext);
+ Sym, MCSymbolRefExpr::VK_WebAssembly_FUNCTION, OutContext);
+ }
return AsmPrinter::lowerConstant(CV);
}
diff --git a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
index 47aadf99e860..b3ce4bd27460 100644
--- a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
+++ b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.cpp
@@ -36,7 +36,7 @@ unsigned WebAssemblyTTIImpl::getNumberOfRegisters(bool Vector) {
return Result;
}
-unsigned WebAssemblyTTIImpl::getRegisterBitWidth(bool Vector) {
+unsigned WebAssemblyTTIImpl::getRegisterBitWidth(bool Vector) const {
if (Vector && getST()->hasSIMD128())
return 128;
diff --git a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h
index f658609f8930..7b35fc916133 100644
--- a/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h
+++ b/lib/Target/WebAssembly/WebAssemblyTargetTransformInfo.h
@@ -55,7 +55,7 @@ public:
/// @{
unsigned getNumberOfRegisters(bool Vector);
- unsigned getRegisterBitWidth(bool Vector);
+ unsigned getRegisterBitWidth(bool Vector) const;
unsigned getArithmeticInstrCost(
unsigned Opcode, Type *Ty,
TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue,
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 831e9bdab0e1..172eba0002d4 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1,4 +1,3 @@
-
//===-- X86ISelLowering.cpp - X86 DAG Lowering Implementation -------------===//
//
// The LLVM Compiler Infrastructure
@@ -5314,20 +5313,37 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits,
assert((SizeInBits % EltSizeInBits) == 0 && "Can't split constant!");
unsigned NumElts = SizeInBits / EltSizeInBits;
- unsigned SrcEltSizeInBits = VT.getScalarSizeInBits();
- unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits;
+ // Bitcast a source array of element bits to the target size.
+ auto CastBitData = [&](APInt &UndefSrcElts, ArrayRef<APInt> SrcEltBits) {
+ unsigned NumSrcElts = UndefSrcElts.getBitWidth();
+ unsigned SrcEltSizeInBits = SrcEltBits[0].getBitWidth();
+ assert((NumSrcElts * SrcEltSizeInBits) == SizeInBits &&
+ "Constant bit sizes don't match");
- // Extract all the undef/constant element data and pack into single bitsets.
- APInt UndefBits(SizeInBits, 0);
- APInt MaskBits(SizeInBits, 0);
-
- // Split the undef/constant single bitset data into the target elements.
- auto SplitBitData = [&]() {
// Don't split if we don't allow undef bits.
bool AllowUndefs = AllowWholeUndefs || AllowPartialUndefs;
- if (UndefBits.getBoolValue() && !AllowUndefs)
+ if (UndefSrcElts.getBoolValue() && !AllowUndefs)
return false;
+ // If we're already the right size, don't bother bitcasting.
+ if (NumSrcElts == NumElts) {
+ UndefElts = UndefSrcElts;
+ EltBits.assign(SrcEltBits.begin(), SrcEltBits.end());
+ return true;
+ }
+
+ // Extract all the undef/constant element data and pack into single bitsets.
+ APInt UndefBits(SizeInBits, 0);
+ APInt MaskBits(SizeInBits, 0);
+
+ for (unsigned i = 0; i != NumSrcElts; ++i) {
+ unsigned BitOffset = i * SrcEltSizeInBits;
+ if (UndefSrcElts[i])
+ UndefBits.setBits(BitOffset, BitOffset + SrcEltSizeInBits);
+ MaskBits.insertBits(SrcEltBits[i], BitOffset);
+ }
+
+ // Split the undef/constant single bitset data into the target elements.
UndefElts = APInt(NumElts, 0);
EltBits.resize(NumElts, APInt(EltSizeInBits, 0));
@@ -5356,20 +5372,19 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits,
// Collect constant bits and insert into mask/undef bit masks.
auto CollectConstantBits = [](const Constant *Cst, APInt &Mask, APInt &Undefs,
- unsigned BitOffset) {
+ unsigned UndefBitIndex) {
if (!Cst)
return false;
if (isa<UndefValue>(Cst)) {
- unsigned CstSizeInBits = Cst->getType()->getPrimitiveSizeInBits();
- Undefs.setBits(BitOffset, BitOffset + CstSizeInBits);
+ Undefs.setBit(UndefBitIndex);
return true;
}
if (auto *CInt = dyn_cast<ConstantInt>(Cst)) {
- Mask.insertBits(CInt->getValue(), BitOffset);
+ Mask = CInt->getValue();
return true;
}
if (auto *CFP = dyn_cast<ConstantFP>(Cst)) {
- Mask.insertBits(CFP->getValueAPF().bitcastToAPInt(), BitOffset);
+ Mask = CFP->getValueAPF().bitcastToAPInt();
return true;
}
return false;
@@ -5377,18 +5392,21 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits,
// Extract constant bits from build vector.
if (ISD::isBuildVectorOfConstantSDNodes(Op.getNode())) {
+ unsigned SrcEltSizeInBits = VT.getScalarSizeInBits();
+ unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits;
+
+ APInt UndefSrcElts(NumSrcElts, 0);
+ SmallVector<APInt, 64> SrcEltBits(NumSrcElts, APInt(SrcEltSizeInBits, 0));
for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
const SDValue &Src = Op.getOperand(i);
- unsigned BitOffset = i * SrcEltSizeInBits;
if (Src.isUndef()) {
- UndefBits.setBits(BitOffset, BitOffset + SrcEltSizeInBits);
+ UndefSrcElts.setBit(i);
continue;
}
auto *Cst = cast<ConstantSDNode>(Src);
- APInt Bits = Cst->getAPIntValue().zextOrTrunc(SrcEltSizeInBits);
- MaskBits.insertBits(Bits, BitOffset);
+ SrcEltBits[i] = Cst->getAPIntValue().zextOrTrunc(SrcEltSizeInBits);
}
- return SplitBitData();
+ return CastBitData(UndefSrcElts, SrcEltBits);
}
// Extract constant bits from constant pool vector.
@@ -5397,27 +5415,33 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits,
if (!CstTy->isVectorTy() || (SizeInBits != CstTy->getPrimitiveSizeInBits()))
return false;
- unsigned CstEltSizeInBits = CstTy->getScalarSizeInBits();
- for (unsigned i = 0, e = CstTy->getVectorNumElements(); i != e; ++i)
- if (!CollectConstantBits(Cst->getAggregateElement(i), MaskBits, UndefBits,
- i * CstEltSizeInBits))
+ unsigned SrcEltSizeInBits = CstTy->getScalarSizeInBits();
+ unsigned NumSrcElts = CstTy->getVectorNumElements();
+
+ APInt UndefSrcElts(NumSrcElts, 0);
+ SmallVector<APInt, 64> SrcEltBits(NumSrcElts, APInt(SrcEltSizeInBits, 0));
+ for (unsigned i = 0; i != NumSrcElts; ++i)
+ if (!CollectConstantBits(Cst->getAggregateElement(i), SrcEltBits[i],
+ UndefSrcElts, i))
return false;
- return SplitBitData();
+ return CastBitData(UndefSrcElts, SrcEltBits);
}
// Extract constant bits from a broadcasted constant pool scalar.
if (Op.getOpcode() == X86ISD::VBROADCAST &&
- EltSizeInBits <= SrcEltSizeInBits) {
+ EltSizeInBits <= VT.getScalarSizeInBits()) {
if (auto *Broadcast = getTargetConstantFromNode(Op.getOperand(0))) {
- APInt Bits(SizeInBits, 0);
- APInt Undefs(SizeInBits, 0);
- if (CollectConstantBits(Broadcast, Bits, Undefs, 0)) {
- for (unsigned i = 0; i != NumSrcElts; ++i) {
- MaskBits |= Bits.shl(i * SrcEltSizeInBits);
- UndefBits |= Undefs.shl(i * SrcEltSizeInBits);
- }
- return SplitBitData();
+ unsigned SrcEltSizeInBits = Broadcast->getType()->getScalarSizeInBits();
+ unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits;
+
+ APInt UndefSrcElts(NumSrcElts, 0);
+ SmallVector<APInt, 64> SrcEltBits(1, APInt(SrcEltSizeInBits, 0));
+ if (CollectConstantBits(Broadcast, SrcEltBits[0], UndefSrcElts, 0)) {
+ if (UndefSrcElts[0])
+ UndefSrcElts.setBits(0, NumSrcElts);
+ SrcEltBits.append(NumSrcElts - 1, SrcEltBits[0]);
+ return CastBitData(UndefSrcElts, SrcEltBits);
}
}
}
@@ -5426,10 +5450,15 @@ static bool getTargetConstantBitsFromNode(SDValue Op, unsigned EltSizeInBits,
if (Op.getOpcode() == X86ISD::VZEXT_MOVL &&
Op.getOperand(0).getOpcode() == ISD::SCALAR_TO_VECTOR &&
isa<ConstantSDNode>(Op.getOperand(0).getOperand(0))) {
+ unsigned SrcEltSizeInBits = VT.getScalarSizeInBits();
+ unsigned NumSrcElts = SizeInBits / SrcEltSizeInBits;
+
+ APInt UndefSrcElts(NumSrcElts, 0);
+ SmallVector<APInt, 64> SrcEltBits;
auto *CN = cast<ConstantSDNode>(Op.getOperand(0).getOperand(0));
- MaskBits = CN->getAPIntValue().zextOrTrunc(SrcEltSizeInBits);
- MaskBits = MaskBits.zext(SizeInBits);
- return SplitBitData();
+ SrcEltBits.push_back(CN->getAPIntValue().zextOrTrunc(SrcEltSizeInBits));
+ SrcEltBits.append(NumSrcElts - 1, APInt(SrcEltSizeInBits, 0));
+ return CastBitData(UndefSrcElts, SrcEltBits);
}
return false;
@@ -6491,16 +6520,7 @@ static SDValue EltsFromConsecutiveLoads(EVT VT, ArrayRef<SDValue> Elts,
SDValue NewLd =
DAG.getLoad(VT, DL, LDBase->getChain(), LDBase->getBasePtr(),
LDBase->getPointerInfo(), LDBase->getAlignment(), MMOFlags);
-
- if (LDBase->hasAnyUseOfValue(1)) {
- SDValue NewChain =
- DAG.getNode(ISD::TokenFactor, DL, MVT::Other, SDValue(LDBase, 1),
- SDValue(NewLd.getNode(), 1));
- DAG.ReplaceAllUsesOfValueWith(SDValue(LDBase, 1), NewChain);
- DAG.UpdateNodeOperands(NewChain.getNode(), SDValue(LDBase, 1),
- SDValue(NewLd.getNode(), 1));
- }
-
+ DAG.makeEquivalentMemoryOrdering(LDBase, NewLd);
return NewLd;
};
@@ -6565,19 +6585,7 @@ static SDValue EltsFromConsecutiveLoads(EVT VT, ArrayRef<SDValue> Elts,
LDBase->getAlignment(),
false/*isVolatile*/, true/*ReadMem*/,
false/*WriteMem*/);
-
- // Make sure the newly-created LOAD is in the same position as LDBase in
- // terms of dependency. We create a TokenFactor for LDBase and ResNode,
- // and update uses of LDBase's output chain to use the TokenFactor.
- if (LDBase->hasAnyUseOfValue(1)) {
- SDValue NewChain =
- DAG.getNode(ISD::TokenFactor, DL, MVT::Other, SDValue(LDBase, 1),
- SDValue(ResNode.getNode(), 1));
- DAG.ReplaceAllUsesOfValueWith(SDValue(LDBase, 1), NewChain);
- DAG.UpdateNodeOperands(NewChain.getNode(), SDValue(LDBase, 1),
- SDValue(ResNode.getNode(), 1));
- }
-
+ DAG.makeEquivalentMemoryOrdering(LDBase, ResNode);
return DAG.getBitcast(VT, ResNode);
}
}
@@ -9930,17 +9938,7 @@ static SDValue lowerVectorShuffleAsBroadcast(const SDLoc &DL, MVT VT,
V = DAG.getLoad(SVT, DL, Ld->getChain(), NewAddr,
DAG.getMachineFunction().getMachineMemOperand(
Ld->getMemOperand(), Offset, SVT.getStoreSize()));
-
- // Make sure the newly-created LOAD is in the same position as Ld in
- // terms of dependency. We create a TokenFactor for Ld and V,
- // and update uses of Ld's output chain to use the TokenFactor.
- if (Ld->hasAnyUseOfValue(1)) {
- SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
- SDValue(Ld, 1), SDValue(V.getNode(), 1));
- DAG.ReplaceAllUsesOfValueWith(SDValue(Ld, 1), NewChain);
- DAG.UpdateNodeOperands(NewChain.getNode(), SDValue(Ld, 1),
- SDValue(V.getNode(), 1));
- }
+ DAG.makeEquivalentMemoryOrdering(Ld, V);
} else if (!BroadcastFromReg) {
// We can't broadcast from a vector register.
return SDValue();
@@ -10891,9 +10889,10 @@ static SDValue lowerV8I16GeneralSingleInputVectorShuffle(
"We need to be changing the number of flipped inputs!");
int PSHUFHalfMask[] = {0, 1, 2, 3};
std::swap(PSHUFHalfMask[FixFreeIdx % 4], PSHUFHalfMask[FixIdx % 4]);
- V = DAG.getNode(FixIdx < 4 ? X86ISD::PSHUFLW : X86ISD::PSHUFHW, DL,
- MVT::v8i16, V,
- getV4X86ShuffleImm8ForMask(PSHUFHalfMask, DL, DAG));
+ V = DAG.getNode(
+ FixIdx < 4 ? X86ISD::PSHUFLW : X86ISD::PSHUFHW, DL,
+ MVT::getVectorVT(MVT::i16, V.getValueSizeInBits() / 16), V,
+ getV4X86ShuffleImm8ForMask(PSHUFHalfMask, DL, DAG));
for (int &M : Mask)
if (M >= 0 && M == FixIdx)
@@ -12007,18 +12006,22 @@ static SDValue lowerV2X128VectorShuffle(const SDLoc &DL, MVT VT, SDValue V1,
// subvector.
bool OnlyUsesV1 = isShuffleEquivalent(V1, V2, Mask, {0, 1, 0, 1});
if (OnlyUsesV1 || isShuffleEquivalent(V1, V2, Mask, {0, 1, 4, 5})) {
- // With AVX2 we should use VPERMQ/VPERMPD to allow memory folding.
+ // With AVX2, use VPERMQ/VPERMPD to allow memory folding.
if (Subtarget.hasAVX2() && V2.isUndef())
return SDValue();
- MVT SubVT = MVT::getVectorVT(VT.getVectorElementType(),
- VT.getVectorNumElements() / 2);
- SDValue LoV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT, V1,
- DAG.getIntPtrConstant(0, DL));
- SDValue HiV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT,
- OnlyUsesV1 ? V1 : V2,
- DAG.getIntPtrConstant(0, DL));
- return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoV, HiV);
+ // With AVX1, use vperm2f128 (below) to allow load folding. Otherwise,
+ // this will likely become vinsertf128 which can't fold a 256-bit memop.
+ if (!isa<LoadSDNode>(peekThroughBitcasts(V1))) {
+ MVT SubVT = MVT::getVectorVT(VT.getVectorElementType(),
+ VT.getVectorNumElements() / 2);
+ SDValue LoV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT, V1,
+ DAG.getIntPtrConstant(0, DL));
+ SDValue HiV = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, SubVT,
+ OnlyUsesV1 ? V1 : V2,
+ DAG.getIntPtrConstant(0, DL));
+ return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, LoV, HiV);
+ }
}
}
@@ -19117,7 +19120,7 @@ static SDValue getScalarMaskingNode(SDValue Op, SDValue Mask,
SDValue IMask = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v1i1, Mask);
if (Op.getOpcode() == X86ISD::FSETCCM ||
- Op.getOpcode() == X86ISD::FSETCCM_RND)
+ Op.getOpcode() == X86ISD::FSETCCM_RND)
return DAG.getNode(ISD::AND, dl, VT, Op, IMask);
if (Op.getOpcode() == X86ISD::VFPCLASSS)
return DAG.getNode(ISD::OR, dl, VT, Op, IMask);
@@ -27968,28 +27971,45 @@ static bool combineX86ShufflesRecursively(ArrayRef<SDValue> SrcOps,
OpMask.size() % RootMask.size() == 0) ||
OpMask.size() == RootMask.size()) &&
"The smaller number of elements must divide the larger.");
- int MaskWidth = std::max<int>(OpMask.size(), RootMask.size());
- int RootRatio = std::max<int>(1, OpMask.size() / RootMask.size());
- int OpRatio = std::max<int>(1, RootMask.size() / OpMask.size());
- assert(((RootRatio == 1 && OpRatio == 1) ||
- (RootRatio == 1) != (OpRatio == 1)) &&
+
+ // This function can be performance-critical, so we rely on the power-of-2
+ // knowledge that we have about the mask sizes to replace div/rem ops with
+ // bit-masks and shifts.
+ assert(isPowerOf2_32(RootMask.size()) && "Non-power-of-2 shuffle mask sizes");
+ assert(isPowerOf2_32(OpMask.size()) && "Non-power-of-2 shuffle mask sizes");
+ unsigned RootMaskSizeLog2 = countTrailingZeros(RootMask.size());
+ unsigned OpMaskSizeLog2 = countTrailingZeros(OpMask.size());
+
+ unsigned MaskWidth = std::max<unsigned>(OpMask.size(), RootMask.size());
+ unsigned RootRatio = std::max<unsigned>(1, OpMask.size() >> RootMaskSizeLog2);
+ unsigned OpRatio = std::max<unsigned>(1, RootMask.size() >> OpMaskSizeLog2);
+ assert((RootRatio == 1 || OpRatio == 1) &&
"Must not have a ratio for both incoming and op masks!");
- SmallVector<int, 64> Mask((unsigned)MaskWidth, SM_SentinelUndef);
+ assert(isPowerOf2_32(MaskWidth) && "Non-power-of-2 shuffle mask sizes");
+ assert(isPowerOf2_32(RootRatio) && "Non-power-of-2 shuffle mask sizes");
+ assert(isPowerOf2_32(OpRatio) && "Non-power-of-2 shuffle mask sizes");
+ unsigned RootRatioLog2 = countTrailingZeros(RootRatio);
+ unsigned OpRatioLog2 = countTrailingZeros(OpRatio);
+
+ SmallVector<int, 64> Mask(MaskWidth, SM_SentinelUndef);
// Merge this shuffle operation's mask into our accumulated mask. Note that
// this shuffle's mask will be the first applied to the input, followed by the
// root mask to get us all the way to the root value arrangement. The reason
// for this order is that we are recursing up the operation chain.
- for (int i = 0; i < MaskWidth; ++i) {
- int RootIdx = i / RootRatio;
+ for (unsigned i = 0; i < MaskWidth; ++i) {
+ unsigned RootIdx = i >> RootRatioLog2;
if (RootMask[RootIdx] < 0) {
// This is a zero or undef lane, we're done.
Mask[i] = RootMask[RootIdx];
continue;
}
- int RootMaskedIdx = RootMask[RootIdx] * RootRatio + i % RootRatio;
+ unsigned RootMaskedIdx =
+ RootRatio == 1
+ ? RootMask[RootIdx]
+ : (RootMask[RootIdx] << RootRatioLog2) + (i & (RootRatio - 1));
// Just insert the scaled root mask value if it references an input other
// than the SrcOp we're currently inserting.
@@ -27999,9 +28019,8 @@ static bool combineX86ShufflesRecursively(ArrayRef<SDValue> SrcOps,
continue;
}
- RootMaskedIdx %= MaskWidth;
-
- int OpIdx = RootMaskedIdx / OpRatio;
+ RootMaskedIdx = RootMaskedIdx & (MaskWidth - 1);
+ unsigned OpIdx = RootMaskedIdx >> OpRatioLog2;
if (OpMask[OpIdx] < 0) {
// The incoming lanes are zero or undef, it doesn't matter which ones we
// are using.
@@ -28010,9 +28029,12 @@ static bool combineX86ShufflesRecursively(ArrayRef<SDValue> SrcOps,
}
// Ok, we have non-zero lanes, map them through to one of the Op's inputs.
- int OpMaskedIdx = OpMask[OpIdx] * OpRatio + RootMaskedIdx % OpRatio;
- OpMaskedIdx %= MaskWidth;
+ unsigned OpMaskedIdx =
+ OpRatio == 1
+ ? OpMask[OpIdx]
+ : (OpMask[OpIdx] << OpRatioLog2) + (RootMaskedIdx & (OpRatio - 1));
+ OpMaskedIdx = OpMaskedIdx & (MaskWidth - 1);
if (OpMask[OpIdx] < (int)OpMask.size()) {
assert(0 <= InputIdx0 && "Unknown target shuffle input");
OpMaskedIdx += InputIdx0 * MaskWidth;
diff --git a/lib/Target/X86/X86InstrAVX512.td b/lib/Target/X86/X86InstrAVX512.td
index d8702693884d..2620679df251 100644
--- a/lib/Target/X86/X86InstrAVX512.td
+++ b/lib/Target/X86/X86InstrAVX512.td
@@ -1631,6 +1631,7 @@ multiclass avx512_icmp_packed<bits<8> opc, string OpcodeStr, SDNode OpNode,
[(set _.KRC:$dst, (OpNode (_.VT _.RC:$src1),
(_.VT (bitconvert (_.LdFrag addr:$src2)))))],
IIC_SSE_ALU_F32P_RM>, EVEX_4V;
+ let isCommutable = IsCommutable in
def rrk : AVX512BI<opc, MRMSrcReg,
(outs _.KRC:$dst), (ins _.KRCWM:$mask, _.RC:$src1, _.RC:$src2),
!strconcat(OpcodeStr, "\t{$src2, $src1, $dst {${mask}}|",
@@ -1764,6 +1765,7 @@ multiclass avx512_icmp_cc<bits<8> opc, string Suffix, SDNode OpNode,
(_.VT (bitconvert (_.LdFrag addr:$src2))),
imm:$cc))],
IIC_SSE_ALU_F32P_RM>, EVEX_4V;
+ let isCommutable = 1 in
def rrik : AVX512AIi8<opc, MRMSrcReg,
(outs _.KRC:$dst), (ins _.KRCWM:$mask, _.RC:$src1, _.RC:$src2,
AVX512ICC:$cc),
diff --git a/lib/Target/X86/X86InstrFragmentsSIMD.td b/lib/Target/X86/X86InstrFragmentsSIMD.td
index 5224a16613cb..c28b35b22977 100644
--- a/lib/Target/X86/X86InstrFragmentsSIMD.td
+++ b/lib/Target/X86/X86InstrFragmentsSIMD.td
@@ -737,19 +737,15 @@ def alignedloadv8f64 : PatFrag<(ops node:$ptr),
def alignedloadv8i64 : PatFrag<(ops node:$ptr),
(v8i64 (alignedload512 node:$ptr))>;
-// Like 'load', but uses special alignment checks suitable for use in
+// Like 'vec128load', but uses special alignment checks suitable for use in
// memory operands in most SSE instructions, which are required to
// be naturally aligned on some targets but not on others. If the subtarget
// allows unaligned accesses, match any load, though this may require
// setting a feature bit in the processor (on startup, for example).
// Opteron 10h and later implement such a feature.
-// Avoid non-temporal aligned loads on supported targets.
-def memop : PatFrag<(ops node:$ptr), (load node:$ptr), [{
- return (Subtarget->hasSSEUnalignedMem() ||
- cast<LoadSDNode>(N)->getAlignment() >= 16) &&
- (!Subtarget->hasSSE41() ||
- !(cast<LoadSDNode>(N)->getAlignment() >= 16 &&
- cast<LoadSDNode>(N)->isNonTemporal()));
+def memop : PatFrag<(ops node:$ptr), (vec128load node:$ptr), [{
+ return Subtarget->hasSSEUnalignedMem() ||
+ cast<LoadSDNode>(N)->getAlignment() >= 16;
}]>;
// 128-bit memop pattern fragments
diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp
index ff5d90c4e78b..f3094b781c49 100644
--- a/lib/Target/X86/X86InstrInfo.cpp
+++ b/lib/Target/X86/X86InstrInfo.cpp
@@ -898,10 +898,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZrr, X86::VPABSDZrm, 0 },
{ X86::VPABSQZrr, X86::VPABSQZrm, 0 },
{ X86::VPABSWZrr, X86::VPABSWZrm, 0 },
+ { X86::VPCONFLICTDZrr, X86::VPCONFLICTDZrm, 0 },
+ { X86::VPCONFLICTQZrr, X86::VPCONFLICTQZrm, 0 },
{ X86::VPERMILPDZri, X86::VPERMILPDZmi, 0 },
{ X86::VPERMILPSZri, X86::VPERMILPSZmi, 0 },
{ X86::VPERMPDZri, X86::VPERMPDZmi, 0 },
{ X86::VPERMQZri, X86::VPERMQZmi, 0 },
+ { X86::VPLZCNTDZrr, X86::VPLZCNTDZrm, 0 },
+ { X86::VPLZCNTQZrr, X86::VPLZCNTQZrm, 0 },
{ X86::VPMOVSXBDZrr, X86::VPMOVSXBDZrm, 0 },
{ X86::VPMOVSXBQZrr, X86::VPMOVSXBQZrm, TB_NO_REVERSE },
{ X86::VPMOVSXBWZrr, X86::VPMOVSXBWZrm, 0 },
@@ -948,10 +952,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZ256rr, X86::VPABSDZ256rm, 0 },
{ X86::VPABSQZ256rr, X86::VPABSQZ256rm, 0 },
{ X86::VPABSWZ256rr, X86::VPABSWZ256rm, 0 },
+ { X86::VPCONFLICTDZ256rr, X86::VPCONFLICTDZ256rm, 0 },
+ { X86::VPCONFLICTQZ256rr, X86::VPCONFLICTQZ256rm, 0 },
{ X86::VPERMILPDZ256ri, X86::VPERMILPDZ256mi, 0 },
{ X86::VPERMILPSZ256ri, X86::VPERMILPSZ256mi, 0 },
{ X86::VPERMPDZ256ri, X86::VPERMPDZ256mi, 0 },
{ X86::VPERMQZ256ri, X86::VPERMQZ256mi, 0 },
+ { X86::VPLZCNTDZ256rr, X86::VPLZCNTDZ256rm, 0 },
+ { X86::VPLZCNTQZ256rr, X86::VPLZCNTQZ256rm, 0 },
{ X86::VPMOVSXBDZ256rr, X86::VPMOVSXBDZ256rm, TB_NO_REVERSE },
{ X86::VPMOVSXBQZ256rr, X86::VPMOVSXBQZ256rm, TB_NO_REVERSE },
{ X86::VPMOVSXBWZ256rr, X86::VPMOVSXBWZ256rm, 0 },
@@ -995,8 +1003,12 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZ128rr, X86::VPABSDZ128rm, 0 },
{ X86::VPABSQZ128rr, X86::VPABSQZ128rm, 0 },
{ X86::VPABSWZ128rr, X86::VPABSWZ128rm, 0 },
+ { X86::VPCONFLICTDZ128rr, X86::VPCONFLICTDZ128rm, 0 },
+ { X86::VPCONFLICTQZ128rr, X86::VPCONFLICTQZ128rm, 0 },
{ X86::VPERMILPDZ128ri, X86::VPERMILPDZ128mi, 0 },
{ X86::VPERMILPSZ128ri, X86::VPERMILPSZ128mi, 0 },
+ { X86::VPLZCNTDZ128rr, X86::VPLZCNTDZ128rm, 0 },
+ { X86::VPLZCNTQZ128rr, X86::VPLZCNTQZ128rm, 0 },
{ X86::VPMOVSXBDZ128rr, X86::VPMOVSXBDZ128rm, TB_NO_REVERSE },
{ X86::VPMOVSXBQZ128rr, X86::VPMOVSXBQZ128rm, TB_NO_REVERSE },
{ X86::VPMOVSXBWZ128rr, X86::VPMOVSXBWZ128rm, TB_NO_REVERSE },
@@ -2312,10 +2324,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZrrkz, X86::VPABSDZrmkz, 0 },
{ X86::VPABSQZrrkz, X86::VPABSQZrmkz, 0 },
{ X86::VPABSWZrrkz, X86::VPABSWZrmkz, 0 },
+ { X86::VPCONFLICTDZrrkz, X86::VPCONFLICTDZrmkz, 0 },
+ { X86::VPCONFLICTQZrrkz, X86::VPCONFLICTQZrmkz, 0 },
{ X86::VPERMILPDZrikz, X86::VPERMILPDZmikz, 0 },
{ X86::VPERMILPSZrikz, X86::VPERMILPSZmikz, 0 },
{ X86::VPERMPDZrikz, X86::VPERMPDZmikz, 0 },
{ X86::VPERMQZrikz, X86::VPERMQZmikz, 0 },
+ { X86::VPLZCNTDZrrkz, X86::VPLZCNTDZrmkz, 0 },
+ { X86::VPLZCNTQZrrkz, X86::VPLZCNTQZrmkz, 0 },
{ X86::VPMOVSXBDZrrkz, X86::VPMOVSXBDZrmkz, 0 },
{ X86::VPMOVSXBQZrrkz, X86::VPMOVSXBQZrmkz, TB_NO_REVERSE },
{ X86::VPMOVSXBWZrrkz, X86::VPMOVSXBWZrmkz, 0 },
@@ -2350,10 +2366,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZ256rrkz, X86::VPABSDZ256rmkz, 0 },
{ X86::VPABSQZ256rrkz, X86::VPABSQZ256rmkz, 0 },
{ X86::VPABSWZ256rrkz, X86::VPABSWZ256rmkz, 0 },
+ { X86::VPCONFLICTDZ256rrkz, X86::VPCONFLICTDZ256rmkz, 0 },
+ { X86::VPCONFLICTQZ256rrkz, X86::VPCONFLICTQZ256rmkz, 0 },
{ X86::VPERMILPDZ256rikz, X86::VPERMILPDZ256mikz, 0 },
{ X86::VPERMILPSZ256rikz, X86::VPERMILPSZ256mikz, 0 },
{ X86::VPERMPDZ256rikz, X86::VPERMPDZ256mikz, 0 },
{ X86::VPERMQZ256rikz, X86::VPERMQZ256mikz, 0 },
+ { X86::VPLZCNTDZ256rrkz, X86::VPLZCNTDZ256rmkz, 0 },
+ { X86::VPLZCNTQZ256rrkz, X86::VPLZCNTQZ256rmkz, 0 },
{ X86::VPMOVSXBDZ256rrkz, X86::VPMOVSXBDZ256rmkz, TB_NO_REVERSE },
{ X86::VPMOVSXBQZ256rrkz, X86::VPMOVSXBQZ256rmkz, TB_NO_REVERSE },
{ X86::VPMOVSXBWZ256rrkz, X86::VPMOVSXBWZ256rmkz, 0 },
@@ -2385,8 +2405,12 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZ128rrkz, X86::VPABSDZ128rmkz, 0 },
{ X86::VPABSQZ128rrkz, X86::VPABSQZ128rmkz, 0 },
{ X86::VPABSWZ128rrkz, X86::VPABSWZ128rmkz, 0 },
+ { X86::VPCONFLICTDZ128rrkz, X86::VPCONFLICTDZ128rmkz, 0 },
+ { X86::VPCONFLICTQZ128rrkz, X86::VPCONFLICTQZ128rmkz, 0 },
{ X86::VPERMILPDZ128rikz, X86::VPERMILPDZ128mikz, 0 },
{ X86::VPERMILPSZ128rikz, X86::VPERMILPSZ128mikz, 0 },
+ { X86::VPLZCNTDZ128rrkz, X86::VPLZCNTDZ128rmkz, 0 },
+ { X86::VPLZCNTQZ128rrkz, X86::VPLZCNTQZ128rmkz, 0 },
{ X86::VPMOVSXBDZ128rrkz, X86::VPMOVSXBDZ128rmkz, TB_NO_REVERSE },
{ X86::VPMOVSXBQZ128rrkz, X86::VPMOVSXBQZ128rmkz, TB_NO_REVERSE },
{ X86::VPMOVSXBWZ128rrkz, X86::VPMOVSXBWZ128rmkz, TB_NO_REVERSE },
@@ -2935,10 +2959,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZrrk, X86::VPABSDZrmk, 0 },
{ X86::VPABSQZrrk, X86::VPABSQZrmk, 0 },
{ X86::VPABSWZrrk, X86::VPABSWZrmk, 0 },
+ { X86::VPCONFLICTDZrrk, X86::VPCONFLICTDZrmk, 0 },
+ { X86::VPCONFLICTQZrrk, X86::VPCONFLICTQZrmk, 0 },
{ X86::VPERMILPDZrik, X86::VPERMILPDZmik, 0 },
{ X86::VPERMILPSZrik, X86::VPERMILPSZmik, 0 },
{ X86::VPERMPDZrik, X86::VPERMPDZmik, 0 },
{ X86::VPERMQZrik, X86::VPERMQZmik, 0 },
+ { X86::VPLZCNTDZrrk, X86::VPLZCNTDZrmk, 0 },
+ { X86::VPLZCNTQZrrk, X86::VPLZCNTQZrmk, 0 },
{ X86::VPMOVSXBDZrrk, X86::VPMOVSXBDZrmk, 0 },
{ X86::VPMOVSXBQZrrk, X86::VPMOVSXBQZrmk, TB_NO_REVERSE },
{ X86::VPMOVSXBWZrrk, X86::VPMOVSXBWZrmk, 0 },
@@ -2973,10 +3001,14 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZ256rrk, X86::VPABSDZ256rmk, 0 },
{ X86::VPABSQZ256rrk, X86::VPABSQZ256rmk, 0 },
{ X86::VPABSWZ256rrk, X86::VPABSWZ256rmk, 0 },
+ { X86::VPCONFLICTDZ256rrk, X86::VPCONFLICTDZ256rmk, 0 },
+ { X86::VPCONFLICTQZ256rrk, X86::VPCONFLICTQZ256rmk, 0 },
{ X86::VPERMILPDZ256rik, X86::VPERMILPDZ256mik, 0 },
{ X86::VPERMILPSZ256rik, X86::VPERMILPSZ256mik, 0 },
{ X86::VPERMPDZ256rik, X86::VPERMPDZ256mik, 0 },
{ X86::VPERMQZ256rik, X86::VPERMQZ256mik, 0 },
+ { X86::VPLZCNTDZ256rrk, X86::VPLZCNTDZ256rmk, 0 },
+ { X86::VPLZCNTQZ256rrk, X86::VPLZCNTQZ256rmk, 0 },
{ X86::VPMOVSXBDZ256rrk, X86::VPMOVSXBDZ256rmk, TB_NO_REVERSE },
{ X86::VPMOVSXBQZ256rrk, X86::VPMOVSXBQZ256rmk, TB_NO_REVERSE },
{ X86::VPMOVSXBWZ256rrk, X86::VPMOVSXBWZ256rmk, 0 },
@@ -3008,8 +3040,12 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPABSDZ128rrk, X86::VPABSDZ128rmk, 0 },
{ X86::VPABSQZ128rrk, X86::VPABSQZ128rmk, 0 },
{ X86::VPABSWZ128rrk, X86::VPABSWZ128rmk, 0 },
+ { X86::VPCONFLICTDZ128rrk, X86::VPCONFLICTDZ128rmk, 0 },
+ { X86::VPCONFLICTQZ128rrk, X86::VPCONFLICTQZ128rmk, 0 },
{ X86::VPERMILPDZ128rik, X86::VPERMILPDZ128mik, 0 },
{ X86::VPERMILPSZ128rik, X86::VPERMILPSZ128mik, 0 },
+ { X86::VPLZCNTDZ128rrk, X86::VPLZCNTDZ128rmk, 0 },
+ { X86::VPLZCNTQZ128rrk, X86::VPLZCNTQZ128rmk, 0 },
{ X86::VPMOVSXBDZ128rrk, X86::VPMOVSXBDZ128rmk, TB_NO_REVERSE },
{ X86::VPMOVSXBQZ128rrk, X86::VPMOVSXBQZ128rmk, TB_NO_REVERSE },
{ X86::VPMOVSXBWZ128rrk, X86::VPMOVSXBWZ128rmk, TB_NO_REVERSE },
@@ -3034,6 +3070,64 @@ X86InstrInfo::X86InstrInfo(X86Subtarget &STI)
{ X86::VPSRLDZ128rik, X86::VPSRLDZ128mik, 0 },
{ X86::VPSRLQZ128rik, X86::VPSRLQZ128mik, 0 },
{ X86::VPSRLWZ128rik, X86::VPSRLWZ128mik, 0 },
+
+ // AVX-512 masked compare instructions
+ { X86::VCMPPDZ128rrik, X86::VCMPPDZ128rmik, 0 },
+ { X86::VCMPPSZ128rrik, X86::VCMPPSZ128rmik, 0 },
+ { X86::VCMPPDZ256rrik, X86::VCMPPDZ256rmik, 0 },
+ { X86::VCMPPSZ256rrik, X86::VCMPPSZ256rmik, 0 },
+ { X86::VCMPPDZrrik, X86::VCMPPDZrmik, 0 },
+ { X86::VCMPPSZrrik, X86::VCMPPSZrmik, 0 },
+ { X86::VCMPSDZrr_Intk, X86::VCMPSDZrm_Intk, TB_NO_REVERSE },
+ { X86::VCMPSSZrr_Intk, X86::VCMPSSZrm_Intk, TB_NO_REVERSE },
+ { X86::VPCMPBZ128rrik, X86::VPCMPBZ128rmik, 0 },
+ { X86::VPCMPBZ256rrik, X86::VPCMPBZ256rmik, 0 },
+ { X86::VPCMPBZrrik, X86::VPCMPBZrmik, 0 },
+ { X86::VPCMPDZ128rrik, X86::VPCMPDZ128rmik, 0 },
+ { X86::VPCMPDZ256rrik, X86::VPCMPDZ256rmik, 0 },
+ { X86::VPCMPDZrrik, X86::VPCMPDZrmik, 0 },
+ { X86::VPCMPEQBZ128rrk, X86::VPCMPEQBZ128rmk, 0 },
+ { X86::VPCMPEQBZ256rrk, X86::VPCMPEQBZ256rmk, 0 },
+ { X86::VPCMPEQBZrrk, X86::VPCMPEQBZrmk, 0 },
+ { X86::VPCMPEQDZ128rrk, X86::VPCMPEQDZ128rmk, 0 },
+ { X86::VPCMPEQDZ256rrk, X86::VPCMPEQDZ256rmk, 0 },
+ { X86::VPCMPEQDZrrk, X86::VPCMPEQDZrmk, 0 },
+ { X86::VPCMPEQQZ128rrk, X86::VPCMPEQQZ128rmk, 0 },
+ { X86::VPCMPEQQZ256rrk, X86::VPCMPEQQZ256rmk, 0 },
+ { X86::VPCMPEQQZrrk, X86::VPCMPEQQZrmk, 0 },
+ { X86::VPCMPEQWZ128rrk, X86::VPCMPEQWZ128rmk, 0 },
+ { X86::VPCMPEQWZ256rrk, X86::VPCMPEQWZ256rmk, 0 },
+ { X86::VPCMPEQWZrrk, X86::VPCMPEQWZrmk, 0 },
+ { X86::VPCMPGTBZ128rrk, X86::VPCMPGTBZ128rmk, 0 },
+ { X86::VPCMPGTBZ256rrk, X86::VPCMPGTBZ256rmk, 0 },
+ { X86::VPCMPGTBZrrk, X86::VPCMPGTBZrmk, 0 },
+ { X86::VPCMPGTDZ128rrk, X86::VPCMPGTDZ128rmk, 0 },
+ { X86::VPCMPGTDZ256rrk, X86::VPCMPGTDZ256rmk, 0 },
+ { X86::VPCMPGTDZrrk, X86::VPCMPGTDZrmk, 0 },
+ { X86::VPCMPGTQZ128rrk, X86::VPCMPGTQZ128rmk, 0 },
+ { X86::VPCMPGTQZ256rrk, X86::VPCMPGTQZ256rmk, 0 },
+ { X86::VPCMPGTQZrrk, X86::VPCMPGTQZrmk, 0 },
+ { X86::VPCMPGTWZ128rrk, X86::VPCMPGTWZ128rmk, 0 },
+ { X86::VPCMPGTWZ256rrk, X86::VPCMPGTWZ256rmk, 0 },
+ { X86::VPCMPGTWZrrk, X86::VPCMPGTWZrmk, 0 },
+ { X86::VPCMPQZ128rrik, X86::VPCMPQZ128rmik, 0 },
+ { X86::VPCMPQZ256rrik, X86::VPCMPQZ256rmik, 0 },
+ { X86::VPCMPQZrrik, X86::VPCMPQZrmik, 0 },
+ { X86::VPCMPUBZ128rrik, X86::VPCMPUBZ128rmik, 0 },
+ { X86::VPCMPUBZ256rrik, X86::VPCMPUBZ256rmik, 0 },
+ { X86::VPCMPUBZrrik, X86::VPCMPUBZrmik, 0 },
+ { X86::VPCMPUDZ128rrik, X86::VPCMPUDZ128rmik, 0 },
+ { X86::VPCMPUDZ256rrik, X86::VPCMPUDZ256rmik, 0 },
+ { X86::VPCMPUDZrrik, X86::VPCMPUDZrmik, 0 },
+ { X86::VPCMPUQZ128rrik, X86::VPCMPUQZ128rmik, 0 },
+ { X86::VPCMPUQZ256rrik, X86::VPCMPUQZ256rmik, 0 },
+ { X86::VPCMPUQZrrik, X86::VPCMPUQZrmik, 0 },
+ { X86::VPCMPUWZ128rrik, X86::VPCMPUWZ128rmik, 0 },
+ { X86::VPCMPUWZ256rrik, X86::VPCMPUWZ256rmik, 0 },
+ { X86::VPCMPUWZrrik, X86::VPCMPUWZrmik, 0 },
+ { X86::VPCMPWZ128rrik, X86::VPCMPWZ128rmik, 0 },
+ { X86::VPCMPWZ256rrik, X86::VPCMPWZ256rmik, 0 },
+ { X86::VPCMPWZrrik, X86::VPCMPWZrmik, 0 },
};
for (X86MemoryFoldTableEntry Entry : MemoryFoldTable3) {
@@ -5136,20 +5230,32 @@ MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
return nullptr;
}
}
- case X86::VPCMPBZ128rri: case X86::VPCMPUBZ128rri:
- case X86::VPCMPBZ256rri: case X86::VPCMPUBZ256rri:
- case X86::VPCMPBZrri: case X86::VPCMPUBZrri:
- case X86::VPCMPDZ128rri: case X86::VPCMPUDZ128rri:
- case X86::VPCMPDZ256rri: case X86::VPCMPUDZ256rri:
- case X86::VPCMPDZrri: case X86::VPCMPUDZrri:
- case X86::VPCMPQZ128rri: case X86::VPCMPUQZ128rri:
- case X86::VPCMPQZ256rri: case X86::VPCMPUQZ256rri:
- case X86::VPCMPQZrri: case X86::VPCMPUQZrri:
- case X86::VPCMPWZ128rri: case X86::VPCMPUWZ128rri:
- case X86::VPCMPWZ256rri: case X86::VPCMPUWZ256rri:
- case X86::VPCMPWZrri: case X86::VPCMPUWZrri: {
+ case X86::VPCMPBZ128rri: case X86::VPCMPUBZ128rri:
+ case X86::VPCMPBZ256rri: case X86::VPCMPUBZ256rri:
+ case X86::VPCMPBZrri: case X86::VPCMPUBZrri:
+ case X86::VPCMPDZ128rri: case X86::VPCMPUDZ128rri:
+ case X86::VPCMPDZ256rri: case X86::VPCMPUDZ256rri:
+ case X86::VPCMPDZrri: case X86::VPCMPUDZrri:
+ case X86::VPCMPQZ128rri: case X86::VPCMPUQZ128rri:
+ case X86::VPCMPQZ256rri: case X86::VPCMPUQZ256rri:
+ case X86::VPCMPQZrri: case X86::VPCMPUQZrri:
+ case X86::VPCMPWZ128rri: case X86::VPCMPUWZ128rri:
+ case X86::VPCMPWZ256rri: case X86::VPCMPUWZ256rri:
+ case X86::VPCMPWZrri: case X86::VPCMPUWZrri:
+ case X86::VPCMPBZ128rrik: case X86::VPCMPUBZ128rrik:
+ case X86::VPCMPBZ256rrik: case X86::VPCMPUBZ256rrik:
+ case X86::VPCMPBZrrik: case X86::VPCMPUBZrrik:
+ case X86::VPCMPDZ128rrik: case X86::VPCMPUDZ128rrik:
+ case X86::VPCMPDZ256rrik: case X86::VPCMPUDZ256rrik:
+ case X86::VPCMPDZrrik: case X86::VPCMPUDZrrik:
+ case X86::VPCMPQZ128rrik: case X86::VPCMPUQZ128rrik:
+ case X86::VPCMPQZ256rrik: case X86::VPCMPUQZ256rrik:
+ case X86::VPCMPQZrrik: case X86::VPCMPUQZrrik:
+ case X86::VPCMPWZ128rrik: case X86::VPCMPUWZ128rrik:
+ case X86::VPCMPWZ256rrik: case X86::VPCMPUWZ256rrik:
+ case X86::VPCMPWZrrik: case X86::VPCMPUWZrrik: {
// Flip comparison mode immediate (if necessary).
- unsigned Imm = MI.getOperand(3).getImm() & 0x7;
+ unsigned Imm = MI.getOperand(MI.getNumOperands() - 1).getImm() & 0x7;
switch (Imm) {
default: llvm_unreachable("Unreachable!");
case 0x01: Imm = 0x06; break; // LT -> NLE
@@ -5163,7 +5269,7 @@ MachineInstr *X86InstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
break;
}
auto &WorkingMI = cloneIfNew(MI);
- WorkingMI.getOperand(3).setImm(Imm);
+ WorkingMI.getOperand(MI.getNumOperands() - 1).setImm(Imm);
return TargetInstrInfo::commuteInstructionImpl(WorkingMI, /*NewMI=*/false,
OpIdx1, OpIdx2);
}
diff --git a/lib/Testing/CMakeLists.txt b/lib/Testing/CMakeLists.txt
new file mode 100644
index 000000000000..fc23e64eeb7a
--- /dev/null
+++ b/lib/Testing/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Support)
diff --git a/lib/Testing/LLVMBuild.txt b/lib/Testing/LLVMBuild.txt
new file mode 100644
index 000000000000..cdf83736298e
--- /dev/null
+++ b/lib/Testing/LLVMBuild.txt
@@ -0,0 +1,19 @@
+;===- ./lib/Testing/LLVMBuild.txt ------------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[common]
+subdirectories = Support
diff --git a/lib/Testing/Support/CMakeLists.txt b/lib/Testing/Support/CMakeLists.txt
new file mode 100644
index 000000000000..fa8dfe59c8bd
--- /dev/null
+++ b/lib/Testing/Support/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_llvm_library(LLVMTestingSupport
+ Error.cpp
+
+ BUILDTREE_ONLY
+
+ ADDITIONAL_HEADER_DIRS
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Testing/Support
+ )
+
+include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include)
+include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include)
+target_link_libraries(LLVMTestingSupport PRIVATE gtest) \ No newline at end of file
diff --git a/lib/Testing/Support/Error.cpp b/lib/Testing/Support/Error.cpp
new file mode 100644
index 000000000000..ce0da44da408
--- /dev/null
+++ b/lib/Testing/Support/Error.cpp
@@ -0,0 +1,22 @@
+//===- llvm/Testing/Support/Error.cpp -------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Testing/Support/Error.h"
+
+#include "llvm/ADT/StringRef.h"
+
+using namespace llvm;
+
+llvm::detail::ErrorHolder llvm::detail::TakeError(llvm::Error Err) {
+ bool Succeeded = !static_cast<bool>(Err);
+ std::string Message;
+ if (!Succeeded)
+ Message = toString(std::move(Err));
+ return {Succeeded, Message};
+}
diff --git a/lib/Testing/Support/LLVMBuild.txt b/lib/Testing/Support/LLVMBuild.txt
new file mode 100644
index 000000000000..40853e8172d5
--- /dev/null
+++ b/lib/Testing/Support/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./Testing/Support/LLVMBuild.txt --------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = TestingSupport
+parent = Libraries
+required_libraries = Support
diff --git a/lib/Transforms/IPO/CrossDSOCFI.cpp b/lib/Transforms/IPO/CrossDSOCFI.cpp
index 1b111de06157..d94aa5da8560 100644
--- a/lib/Transforms/IPO/CrossDSOCFI.cpp
+++ b/lib/Transforms/IPO/CrossDSOCFI.cpp
@@ -95,6 +95,17 @@ void CrossDSOCFI::buildCFICheck(Module &M) {
}
}
+ NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
+ if (CfiFunctionsMD) {
+ for (auto Func : CfiFunctionsMD->operands()) {
+ assert(Func->getNumOperands() >= 2);
+ for (unsigned I = 2; I < Func->getNumOperands(); ++I)
+ if (ConstantInt *TypeId =
+ extractNumericTypeId(cast<MDNode>(Func->getOperand(I).get())))
+ TypeIds.insert(TypeId->getZExtValue());
+ }
+ }
+
LLVMContext &Ctx = M.getContext();
Constant *C = M.getOrInsertFunction(
"__cfi_check", Type::getVoidTy(Ctx), Type::getInt64Ty(Ctx),
diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp
index c0dfeede05c5..ad89e40661c6 100644
--- a/lib/Transforms/IPO/Inliner.cpp
+++ b/lib/Transforms/IPO/Inliner.cpp
@@ -523,40 +523,47 @@ inlineCallsImpl(CallGraphSCC &SCC, CallGraph &CG,
if (!Callee || Callee->isDeclaration())
continue;
- // If this call site is dead and it is to a readonly function, we should
- // just delete the call instead of trying to inline it, regardless of
- // size. This happens because IPSCCP propagates the result out of the
- // call and then we're left with the dead call.
- if (isInstructionTriviallyDead(CS.getInstruction(), &TLI)) {
- DEBUG(dbgs() << " -> Deleting dead call: " << *CS.getInstruction()
- << "\n");
- // Update the call graph by deleting the edge from Callee to Caller.
- CG[Caller]->removeCallEdgeFor(CS);
- CS.getInstruction()->eraseFromParent();
- ++NumCallsDeleted;
- } else {
+ Instruction *Instr = CS.getInstruction();
+
+ bool IsTriviallyDead = isInstructionTriviallyDead(Instr, &TLI);
+
+ int InlineHistoryID;
+ if (!IsTriviallyDead) {
// If this call site was obtained by inlining another function, verify
// that the include path for the function did not include the callee
// itself. If so, we'd be recursively inlining the same function,
// which would provide the same callsites, which would cause us to
// infinitely inline.
- int InlineHistoryID = CallSites[CSi].second;
+ InlineHistoryID = CallSites[CSi].second;
if (InlineHistoryID != -1 &&
InlineHistoryIncludes(Callee, InlineHistoryID, InlineHistory))
continue;
+ }
+ // FIXME for new PM: because of the old PM we currently generate ORE and
+ // in turn BFI on demand. With the new PM, the ORE dependency should
+ // just become a regular analysis dependency.
+ OptimizationRemarkEmitter ORE(Caller);
+
+ // If the policy determines that we should inline this function,
+ // delete the call instead.
+ if (!shouldInline(CS, GetInlineCost, ORE))
+ continue;
+
+ // If this call site is dead and it is to a readonly function, we should
+ // just delete the call instead of trying to inline it, regardless of
+ // size. This happens because IPSCCP propagates the result out of the
+ // call and then we're left with the dead call.
+ if (IsTriviallyDead) {
+ DEBUG(dbgs() << " -> Deleting dead call: " << *Instr << "\n");
+ // Update the call graph by deleting the edge from Callee to Caller.
+ CG[Caller]->removeCallEdgeFor(CS);
+ Instr->eraseFromParent();
+ ++NumCallsDeleted;
+ } else {
// Get DebugLoc to report. CS will be invalid after Inliner.
- DebugLoc DLoc = CS.getInstruction()->getDebugLoc();
+ DebugLoc DLoc = Instr->getDebugLoc();
BasicBlock *Block = CS.getParent();
- // FIXME for new PM: because of the old PM we currently generate ORE and
- // in turn BFI on demand. With the new PM, the ORE dependency should
- // just become a regular analysis dependency.
- OptimizationRemarkEmitter ORE(Caller);
-
- // If the policy determines that we should inline this function,
- // try to do so.
- if (!shouldInline(CS, GetInlineCost, ORE))
- continue;
// Attempt to inline the function.
using namespace ore;
diff --git a/lib/Transforms/IPO/LowerTypeTests.cpp b/lib/Transforms/IPO/LowerTypeTests.cpp
index 90896d285f5a..b406c22c69d7 100644
--- a/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/TypeMetadataUtils.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
@@ -206,17 +207,26 @@ struct ByteArrayInfo {
class GlobalTypeMember final : TrailingObjects<GlobalTypeMember, MDNode *> {
GlobalObject *GO;
size_t NTypes;
+ // For functions: true if this is a definition (either in the merged module or
+ // in one of the thinlto modules).
+ bool IsDefinition;
+ // For functions: true if this function is either defined or used in a thinlto
+ // module and its jumptable entry needs to be exported to thinlto backends.
+ bool IsExported;
friend TrailingObjects;
size_t numTrailingObjects(OverloadToken<MDNode *>) const { return NTypes; }
public:
static GlobalTypeMember *create(BumpPtrAllocator &Alloc, GlobalObject *GO,
+ bool IsDefinition, bool IsExported,
ArrayRef<MDNode *> Types) {
auto *GTM = static_cast<GlobalTypeMember *>(Alloc.Allocate(
totalSizeToAlloc<MDNode *>(Types.size()), alignof(GlobalTypeMember)));
GTM->GO = GO;
GTM->NTypes = Types.size();
+ GTM->IsDefinition = IsDefinition;
+ GTM->IsExported = IsExported;
std::uninitialized_copy(Types.begin(), Types.end(),
GTM->getTrailingObjects<MDNode *>());
return GTM;
@@ -224,6 +234,12 @@ public:
GlobalObject *getGlobal() const {
return GO;
}
+ bool isDefinition() const {
+ return IsDefinition;
+ }
+ bool isExported() const {
+ return IsExported;
+ }
ArrayRef<MDNode *> types() const {
return makeArrayRef(getTrailingObjects<MDNode *>(), NTypes);
}
@@ -294,6 +310,7 @@ class LowerTypeTestsModule {
void exportTypeId(StringRef TypeId, const TypeIdLowering &TIL);
TypeIdLowering importTypeId(StringRef TypeId);
void importTypeTest(CallInst *CI);
+ void importFunction(Function *F, bool isDefinition);
BitSetInfo
buildBitSet(Metadata *TypeId,
@@ -820,6 +837,41 @@ void LowerTypeTestsModule::importTypeTest(CallInst *CI) {
CI->eraseFromParent();
}
+// ThinLTO backend: the function F has a jump table entry; update this module
+// accordingly. isDefinition describes the type of the jump table entry.
+void LowerTypeTestsModule::importFunction(Function *F, bool isDefinition) {
+ assert(F->getType()->getAddressSpace() == 0);
+
+ // Declaration of a local function - nothing to do.
+ if (F->isDeclarationForLinker() && isDefinition)
+ return;
+
+ GlobalValue::VisibilityTypes Visibility = F->getVisibility();
+ std::string Name = F->getName();
+ Function *FDecl;
+
+ if (F->isDeclarationForLinker() && !isDefinition) {
+ // Declaration of an external function.
+ FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage,
+ Name + ".cfi_jt", &M);
+ FDecl->setVisibility(GlobalValue::HiddenVisibility);
+ } else {
+ // Definition.
+ assert(isDefinition);
+ F->setName(Name + ".cfi");
+ F->setLinkage(GlobalValue::ExternalLinkage);
+ F->setVisibility(GlobalValue::HiddenVisibility);
+ FDecl = Function::Create(F->getFunctionType(), GlobalValue::ExternalLinkage,
+ Name, &M);
+ FDecl->setVisibility(Visibility);
+ }
+
+ if (F->isWeakForLinker())
+ replaceWeakDeclarationWithJumpTablePtr(F, FDecl);
+ else
+ F->replaceAllUsesWith(FDecl);
+}
+
void LowerTypeTestsModule::lowerTypeTestCalls(
ArrayRef<Metadata *> TypeIds, Constant *CombinedGlobalAddr,
const DenseMap<GlobalTypeMember *, uint64_t> &GlobalLayout) {
@@ -1143,7 +1195,6 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
// arithmetic that we normally use for globals.
// FIXME: find a better way to represent the jumptable in the IR.
-
assert(!Functions.empty());
// Build a simple layout based on the regular layout of jump tables.
@@ -1167,6 +1218,7 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
// references to the original functions with references to the aliases.
for (unsigned I = 0; I != Functions.size(); ++I) {
Function *F = cast<Function>(Functions[I]->getGlobal());
+ bool IsDefinition = Functions[I]->isDefinition();
Constant *CombinedGlobalElemPtr = ConstantExpr::getBitCast(
ConstantExpr::getInBoundsGetElementPtr(
@@ -1174,7 +1226,18 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
ArrayRef<Constant *>{ConstantInt::get(IntPtrTy, 0),
ConstantInt::get(IntPtrTy, I)}),
F->getType());
- if (F->isDeclarationForLinker()) {
+ if (Functions[I]->isExported()) {
+ if (IsDefinition) {
+ ExportSummary->cfiFunctionDefs().insert(F->getName());
+ } else {
+ GlobalAlias *JtAlias = GlobalAlias::create(
+ F->getValueType(), 0, GlobalValue::ExternalLinkage,
+ F->getName() + ".cfi_jt", CombinedGlobalElemPtr, &M);
+ JtAlias->setVisibility(GlobalValue::HiddenVisibility);
+ ExportSummary->cfiFunctionDecls().insert(F->getName());
+ }
+ }
+ if (!IsDefinition) {
if (F->isWeakForLinker())
replaceWeakDeclarationWithJumpTablePtr(F, CombinedGlobalElemPtr);
else
@@ -1182,9 +1245,8 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
} else {
assert(F->getType()->getAddressSpace() == 0);
- GlobalAlias *FAlias = GlobalAlias::create(F->getValueType(), 0,
- F->getLinkage(), "",
- CombinedGlobalElemPtr, &M);
+ GlobalAlias *FAlias = GlobalAlias::create(
+ F->getValueType(), 0, F->getLinkage(), "", CombinedGlobalElemPtr, &M);
FAlias->setVisibility(F->getVisibility());
FAlias->takeName(F);
if (FAlias->hasName())
@@ -1353,15 +1415,37 @@ bool LowerTypeTestsModule::runForTesting(Module &M) {
bool LowerTypeTestsModule::lower() {
Function *TypeTestFunc =
M.getFunction(Intrinsic::getName(Intrinsic::type_test));
- if ((!TypeTestFunc || TypeTestFunc->use_empty()) && !ExportSummary)
+ if ((!TypeTestFunc || TypeTestFunc->use_empty()) && !ExportSummary &&
+ !ImportSummary)
return false;
if (ImportSummary) {
- for (auto UI = TypeTestFunc->use_begin(), UE = TypeTestFunc->use_end();
- UI != UE;) {
- auto *CI = cast<CallInst>((*UI++).getUser());
- importTypeTest(CI);
+ if (TypeTestFunc) {
+ for (auto UI = TypeTestFunc->use_begin(), UE = TypeTestFunc->use_end();
+ UI != UE;) {
+ auto *CI = cast<CallInst>((*UI++).getUser());
+ importTypeTest(CI);
+ }
+ }
+
+ SmallVector<Function *, 8> Defs;
+ SmallVector<Function *, 8> Decls;
+ for (auto &F : M) {
+ // CFI functions are either external, or promoted. A local function may
+ // have the same name, but it's not the one we are looking for.
+ if (F.hasLocalLinkage())
+ continue;
+ if (ImportSummary->cfiFunctionDefs().count(F.getName()))
+ Defs.push_back(&F);
+ else if (ImportSummary->cfiFunctionDecls().count(F.getName()))
+ Decls.push_back(&F);
}
+
+ for (auto F : Defs)
+ importFunction(F, /*isDefinition*/ true);
+ for (auto F : Decls)
+ importFunction(F, /*isDefinition*/ false);
+
return true;
}
@@ -1387,6 +1471,58 @@ bool LowerTypeTestsModule::lower() {
llvm::DenseMap<Metadata *, TIInfo> TypeIdInfo;
unsigned I = 0;
SmallVector<MDNode *, 2> Types;
+
+ struct ExportedFunctionInfo {
+ CfiFunctionLinkage Linkage;
+ MDNode *FuncMD; // {name, linkage, type[, type...]}
+ };
+ DenseMap<StringRef, ExportedFunctionInfo> ExportedFunctions;
+ if (ExportSummary) {
+ NamedMDNode *CfiFunctionsMD = M.getNamedMetadata("cfi.functions");
+ if (CfiFunctionsMD) {
+ for (auto FuncMD : CfiFunctionsMD->operands()) {
+ assert(FuncMD->getNumOperands() >= 2);
+ StringRef FunctionName =
+ cast<MDString>(FuncMD->getOperand(0))->getString();
+ if (!ExportSummary->isGUIDLive(GlobalValue::getGUID(
+ GlobalValue::dropLLVMManglingEscape(FunctionName))))
+ continue;
+ CfiFunctionLinkage Linkage = static_cast<CfiFunctionLinkage>(
+ cast<ConstantAsMetadata>(FuncMD->getOperand(1))
+ ->getValue()
+ ->getUniqueInteger()
+ .getZExtValue());
+ auto P = ExportedFunctions.insert({FunctionName, {Linkage, FuncMD}});
+ if (!P.second && P.first->second.Linkage != CFL_Definition)
+ P.first->second = {Linkage, FuncMD};
+ }
+
+ for (const auto &P : ExportedFunctions) {
+ StringRef FunctionName = P.first;
+ CfiFunctionLinkage Linkage = P.second.Linkage;
+ MDNode *FuncMD = P.second.FuncMD;
+ Function *F = M.getFunction(FunctionName);
+ if (!F)
+ F = Function::Create(
+ FunctionType::get(Type::getVoidTy(M.getContext()), false),
+ GlobalVariable::ExternalLinkage, FunctionName, &M);
+
+ if (Linkage == CFL_Definition)
+ F->eraseMetadata(LLVMContext::MD_type);
+
+ if (F->isDeclaration()) {
+ if (Linkage == CFL_WeakDeclaration)
+ F->setLinkage(GlobalValue::ExternalWeakLinkage);
+
+ SmallVector<MDNode *, 2> Types;
+ for (unsigned I = 2; I < FuncMD->getNumOperands(); ++I)
+ F->addMetadata(LLVMContext::MD_type,
+ *cast<MDNode>(FuncMD->getOperand(I).get()));
+ }
+ }
+ }
+ }
+
for (GlobalObject &GO : M.global_objects()) {
if (isa<GlobalVariable>(GO) && GO.isDeclarationForLinker())
continue;
@@ -1396,7 +1532,15 @@ bool LowerTypeTestsModule::lower() {
if (Types.empty())
continue;
- auto *GTM = GlobalTypeMember::create(Alloc, &GO, Types);
+ bool IsDefinition = !GO.isDeclarationForLinker();
+ bool IsExported = false;
+ if (isa<Function>(GO) && ExportedFunctions.count(GO.getName())) {
+ IsDefinition |= ExportedFunctions[GO.getName()].Linkage == CFL_Definition;
+ IsExported = true;
+ }
+
+ auto *GTM =
+ GlobalTypeMember::create(Alloc, &GO, IsDefinition, IsExported, Types);
for (MDNode *Type : Types) {
verifyTypeMDNode(&GO, Type);
auto &Info = TypeIdInfo[cast<MDNode>(Type)->getOperand(1)];
diff --git a/lib/Transforms/IPO/PartialInlining.cpp b/lib/Transforms/IPO/PartialInlining.cpp
index ea805efc66b7..8840435af642 100644
--- a/lib/Transforms/IPO/PartialInlining.cpp
+++ b/lib/Transforms/IPO/PartialInlining.cpp
@@ -103,6 +103,35 @@ struct PartialInlinerImpl {
bool run(Module &M);
Function *unswitchFunction(Function *F);
+ // This class speculatively clones the the function to be partial inlined.
+ // At the end of partial inlining, the remaining callsites to the cloned
+ // function that are not partially inlined will be fixed up to reference
+ // the original function, and the cloned function will be erased.
+ struct FunctionCloner {
+ FunctionCloner(Function *F, FunctionOutliningInfo *OI);
+ ~FunctionCloner();
+
+ // Prepare for function outlining: making sure there is only
+ // one incoming edge from the extracted/outlined region to
+ // the return block.
+ void NormalizeReturnBlock();
+
+ // Do function outlining:
+ Function *doFunctionOutlining();
+
+ Function *OrigFunc = nullptr;
+ Function *ClonedFunc = nullptr;
+ Function *OutlinedFunc = nullptr;
+ BasicBlock *OutliningCallBB = nullptr;
+ // ClonedFunc is inlined in one of its callers after function
+ // outlining.
+ bool IsFunctionInlined = false;
+ // The cost of the region to be outlined.
+ int OutlinedRegionCost = 0;
+ std::unique_ptr<FunctionOutliningInfo> ClonedOI = nullptr;
+ std::unique_ptr<BlockFrequencyInfo> ClonedFuncBFI = nullptr;
+ };
+
private:
int NumPartialInlining = 0;
std::function<AssumptionCache &(Function &)> *GetAssumptionCache;
@@ -114,27 +143,18 @@ private:
// The result is no larger than 1 and is represented using BP.
// (Note that the outlined region's 'head' block can only have incoming
// edges from the guarding entry blocks).
- BranchProbability getOutliningCallBBRelativeFreq(Function *F,
- FunctionOutliningInfo *OI,
- Function *DuplicateFunction,
- BlockFrequencyInfo *BFI,
- BasicBlock *OutliningCallBB);
+ BranchProbability getOutliningCallBBRelativeFreq(FunctionCloner &Cloner);
// Return true if the callee of CS should be partially inlined with
// profit.
- bool shouldPartialInline(CallSite CS, Function *F, FunctionOutliningInfo *OI,
- BlockFrequencyInfo *CalleeBFI,
- BasicBlock *OutliningCallBB,
- int OutliningCallOverhead,
+ bool shouldPartialInline(CallSite CS, FunctionCloner &Cloner,
+ BlockFrequency WeightedOutliningRcost,
OptimizationRemarkEmitter &ORE);
// Try to inline DuplicateFunction (cloned from F with call to
// the OutlinedFunction into its callers. Return true
// if there is any successful inlining.
- bool tryPartialInline(Function *DuplicateFunction,
- Function *F, /*orignal function */
- FunctionOutliningInfo *OI, Function *OutlinedFunction,
- BlockFrequencyInfo *CalleeBFI);
+ bool tryPartialInline(FunctionCloner &Cloner);
// Compute the mapping from use site of DuplicationFunction to the enclosing
// BB's profile count.
@@ -146,7 +166,7 @@ private:
NumPartialInlining >= MaxNumPartialInlining);
}
- CallSite getCallSite(User *U) {
+ static CallSite getCallSite(User *U) {
CallSite CS;
if (CallInst *CI = dyn_cast<CallInst>(U))
CS = CallSite(CI);
@@ -157,7 +177,7 @@ private:
return CS;
}
- CallSite getOneCallSiteTo(Function *F) {
+ static CallSite getOneCallSiteTo(Function *F) {
User *User = *F->user_begin();
return getCallSite(User);
}
@@ -171,20 +191,15 @@ private:
// Returns the costs associated with function outlining:
// - The first value is the non-weighted runtime cost for making the call
- // to the outlined function 'OutlinedFunction', including the addtional
- // setup cost in the outlined function itself;
+ // to the outlined function, including the addtional setup cost in the
+ // outlined function itself;
// - The second value is the estimated size of the new call sequence in
- // basic block 'OutliningCallBB';
- // - The third value is the estimated size of the original code from
- // function 'F' that is extracted into the outlined function.
- std::tuple<int, int, int>
- computeOutliningCosts(Function *F, const FunctionOutliningInfo *OutliningInfo,
- Function *OutlinedFunction,
- BasicBlock *OutliningCallBB);
+ // basic block Cloner.OutliningCallBB;
+ std::tuple<int, int> computeOutliningCosts(FunctionCloner &Cloner);
// Compute the 'InlineCost' of block BB. InlineCost is a proxy used to
// approximate both the size and runtime cost (Note that in the current
// inline cost analysis, there is no clear distinction there either).
- int computeBBInlineCost(BasicBlock *BB);
+ static int computeBBInlineCost(BasicBlock *BB);
std::unique_ptr<FunctionOutliningInfo> computeOutliningInfo(Function *F);
@@ -396,19 +411,19 @@ static bool hasProfileData(Function *F, FunctionOutliningInfo *OI) {
return false;
}
-BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq(
- Function *F, FunctionOutliningInfo *OI, Function *DuplicateFunction,
- BlockFrequencyInfo *BFI, BasicBlock *OutliningCallBB) {
+BranchProbability
+PartialInlinerImpl::getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) {
auto EntryFreq =
- BFI->getBlockFreq(&DuplicateFunction->getEntryBlock());
- auto OutliningCallFreq = BFI->getBlockFreq(OutliningCallBB);
+ Cloner.ClonedFuncBFI->getBlockFreq(&Cloner.ClonedFunc->getEntryBlock());
+ auto OutliningCallFreq =
+ Cloner.ClonedFuncBFI->getBlockFreq(Cloner.OutliningCallBB);
auto OutlineRegionRelFreq =
BranchProbability::getBranchProbability(OutliningCallFreq.getFrequency(),
EntryFreq.getFrequency());
- if (hasProfileData(F, OI))
+ if (hasProfileData(Cloner.OrigFunc, Cloner.ClonedOI.get()))
return OutlineRegionRelFreq;
// When profile data is not available, we need to be conservative in
@@ -433,15 +448,17 @@ BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq(
}
bool PartialInlinerImpl::shouldPartialInline(
- CallSite CS, Function *F /* Original Callee */, FunctionOutliningInfo *OI,
- BlockFrequencyInfo *CalleeBFI, BasicBlock *OutliningCallBB,
- int NonWeightedOutliningRcost, OptimizationRemarkEmitter &ORE) {
+ CallSite CS, FunctionCloner &Cloner, BlockFrequency WeightedOutliningRcost,
+ OptimizationRemarkEmitter &ORE) {
+
using namespace ore;
if (SkipCostAnalysis)
return true;
Instruction *Call = CS.getInstruction();
Function *Callee = CS.getCalledFunction();
+ assert(Callee == Cloner.ClonedFunc);
+
Function *Caller = CS.getCaller();
auto &CalleeTTI = (*GetTTI)(*Callee);
InlineCost IC = getInlineCost(CS, getInlineParams(), CalleeTTI,
@@ -449,14 +466,14 @@ bool PartialInlinerImpl::shouldPartialInline(
if (IC.isAlways()) {
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AlwaysInline", Call)
- << NV("Callee", F)
+ << NV("Callee", Cloner.OrigFunc)
<< " should always be fully inlined, not partially");
return false;
}
if (IC.isNever()) {
ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", Call)
- << NV("Callee", F) << " not partially inlined into "
+ << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
<< NV("Caller", Caller)
<< " because it should never be inlined (cost=never)");
return false;
@@ -464,29 +481,25 @@ bool PartialInlinerImpl::shouldPartialInline(
if (!IC) {
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly", Call)
- << NV("Callee", F) << " not partially inlined into "
+ << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
<< NV("Caller", Caller) << " because too costly to inline (cost="
<< NV("Cost", IC.getCost()) << ", threshold="
<< NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")");
return false;
}
const DataLayout &DL = Caller->getParent()->getDataLayout();
+
// The savings of eliminating the call:
int NonWeightedSavings = getCallsiteCost(CS, DL);
BlockFrequency NormWeightedSavings(NonWeightedSavings);
- auto RelativeFreq =
- getOutliningCallBBRelativeFreq(F, OI, Callee, CalleeBFI, OutliningCallBB);
- auto NormWeightedRcost =
- BlockFrequency(NonWeightedOutliningRcost) * RelativeFreq;
-
// Weighted saving is smaller than weighted cost, return false
- if (NormWeightedSavings < NormWeightedRcost) {
+ if (NormWeightedSavings < WeightedOutliningRcost) {
ORE.emit(
OptimizationRemarkAnalysis(DEBUG_TYPE, "OutliningCallcostTooHigh", Call)
- << NV("Callee", F) << " not partially inlined into "
+ << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
<< NV("Caller", Caller) << " runtime overhead (overhead="
- << NV("Overhead", (unsigned)NormWeightedRcost.getFrequency())
+ << NV("Overhead", (unsigned)WeightedOutliningRcost.getFrequency())
<< ", savings="
<< NV("Savings", (unsigned)NormWeightedSavings.getFrequency()) << ")"
<< " of making the outlined call is too high");
@@ -495,7 +508,7 @@ bool PartialInlinerImpl::shouldPartialInline(
}
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "CanBePartiallyInlined", Call)
- << NV("Callee", F) << " can be partially inlined into "
+ << NV("Callee", Cloner.OrigFunc) << " can be partially inlined into "
<< NV("Caller", Caller) << " with cost=" << NV("Cost", IC.getCost())
<< " (threshold="
<< NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")");
@@ -551,50 +564,32 @@ int PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB) {
return InlineCost;
}
-std::tuple<int, int, int> PartialInlinerImpl::computeOutliningCosts(
- Function *F, const FunctionOutliningInfo *OI, Function *OutlinedFunction,
- BasicBlock *OutliningCallBB) {
- // First compute the cost of the outlined region 'OI' in the original
- // function 'F'.
- // FIXME: The code extractor (outliner) can now do code sinking/hoisting
- // to reduce outlining cost. The hoisted/sunk code currently do not
- // incur any runtime cost so it is still OK to compare the outlined
- // function cost with the outlined region in the original function.
- // If this ever changes, we will need to introduce new extractor api
- // to pass the information.
- int OutlinedRegionCost = 0;
- for (BasicBlock &BB : *F) {
- if (&BB != OI->ReturnBlock &&
- // Assuming Entry set is small -- do a linear search here:
- std::find(OI->Entries.begin(), OI->Entries.end(), &BB) ==
- OI->Entries.end()) {
- OutlinedRegionCost += computeBBInlineCost(&BB);
- }
- }
+std::tuple<int, int>
+PartialInlinerImpl::computeOutliningCosts(FunctionCloner &Cloner) {
// Now compute the cost of the call sequence to the outlined function
// 'OutlinedFunction' in BB 'OutliningCallBB':
- int OutliningFuncCallCost = computeBBInlineCost(OutliningCallBB);
+ int OutliningFuncCallCost = computeBBInlineCost(Cloner.OutliningCallBB);
// Now compute the cost of the extracted/outlined function itself:
int OutlinedFunctionCost = 0;
- for (BasicBlock &BB : *OutlinedFunction) {
+ for (BasicBlock &BB : *Cloner.OutlinedFunc) {
OutlinedFunctionCost += computeBBInlineCost(&BB);
}
- assert(OutlinedFunctionCost >= OutlinedRegionCost &&
+ assert(OutlinedFunctionCost >= Cloner.OutlinedRegionCost &&
"Outlined function cost should be no less than the outlined region");
// The code extractor introduces a new root and exit stub blocks with
// additional unconditional branches. Those branches will be eliminated
// later with bb layout. The cost should be adjusted accordingly:
OutlinedFunctionCost -= 2 * InlineConstants::InstrCost;
- int OutliningRuntimeOverhead = OutliningFuncCallCost +
- (OutlinedFunctionCost - OutlinedRegionCost) +
- ExtraOutliningPenalty;
+ int OutliningRuntimeOverhead =
+ OutliningFuncCallCost +
+ (OutlinedFunctionCost - Cloner.OutlinedRegionCost) +
+ ExtraOutliningPenalty;
- return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead,
- OutlinedRegionCost);
+ return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead);
}
// Create the callsite to profile count map which is
@@ -641,42 +636,30 @@ void PartialInlinerImpl::computeCallsiteToProfCountMap(
}
}
-Function *PartialInlinerImpl::unswitchFunction(Function *F) {
-
- if (F->hasAddressTaken())
- return nullptr;
-
- // Let inliner handle it
- if (F->hasFnAttribute(Attribute::AlwaysInline))
- return nullptr;
-
- if (F->hasFnAttribute(Attribute::NoInline))
- return nullptr;
-
- if (PSI->isFunctionEntryCold(F))
- return nullptr;
-
- if (F->user_begin() == F->user_end())
- return nullptr;
-
- std::unique_ptr<FunctionOutliningInfo> OI = computeOutliningInfo(F);
-
- if (!OI)
- return nullptr;
+PartialInlinerImpl::FunctionCloner::FunctionCloner(Function *F,
+ FunctionOutliningInfo *OI)
+ : OrigFunc(F) {
+ ClonedOI = llvm::make_unique<FunctionOutliningInfo>();
// Clone the function, so that we can hack away on it.
ValueToValueMapTy VMap;
- Function *DuplicateFunction = CloneFunction(F, VMap);
- BasicBlock *NewReturnBlock = cast<BasicBlock>(VMap[OI->ReturnBlock]);
- BasicBlock *NewNonReturnBlock = cast<BasicBlock>(VMap[OI->NonReturnBlock]);
- DenseSet<BasicBlock *> NewEntries;
+ ClonedFunc = CloneFunction(F, VMap);
+
+ ClonedOI->ReturnBlock = cast<BasicBlock>(VMap[OI->ReturnBlock]);
+ ClonedOI->NonReturnBlock = cast<BasicBlock>(VMap[OI->NonReturnBlock]);
for (BasicBlock *BB : OI->Entries) {
- NewEntries.insert(cast<BasicBlock>(VMap[BB]));
+ ClonedOI->Entries.push_back(cast<BasicBlock>(VMap[BB]));
+ }
+ for (BasicBlock *E : OI->ReturnBlockPreds) {
+ BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
+ ClonedOI->ReturnBlockPreds.push_back(NewE);
}
-
// Go ahead and update all uses to the duplicate, so that we can just
// use the inliner functionality when we're done hacking.
- F->replaceAllUsesWith(DuplicateFunction);
+ F->replaceAllUsesWith(ClonedFunc);
+}
+
+void PartialInlinerImpl::FunctionCloner::NormalizeReturnBlock() {
auto getFirstPHI = [](BasicBlock *BB) {
BasicBlock::iterator I = BB->begin();
@@ -692,14 +675,19 @@ Function *PartialInlinerImpl::unswitchFunction(Function *F) {
}
return FirstPhi;
};
+
// Special hackery is needed with PHI nodes that have inputs from more than
// one extracted block. For simplicity, just split the PHIs into a two-level
// sequence of PHIs, some of which will go in the extracted region, and some
// of which will go outside.
- BasicBlock *PreReturn = NewReturnBlock;
+ BasicBlock *PreReturn = ClonedOI->ReturnBlock;
// only split block when necessary:
PHINode *FirstPhi = getFirstPHI(PreReturn);
- unsigned NumPredsFromEntries = OI->ReturnBlockPreds.size();
+ unsigned NumPredsFromEntries = ClonedOI->ReturnBlockPreds.size();
+
+ if (!FirstPhi || FirstPhi->getNumIncomingValues() <= NumPredsFromEntries + 1)
+ return;
+
auto IsTrivialPhi = [](PHINode *PN) -> Value * {
Value *CommonValue = PN->getIncomingValue(0);
if (all_of(PN->incoming_values(),
@@ -708,143 +696,185 @@ Function *PartialInlinerImpl::unswitchFunction(Function *F) {
return nullptr;
};
- if (FirstPhi && FirstPhi->getNumIncomingValues() > NumPredsFromEntries + 1) {
-
- NewReturnBlock = NewReturnBlock->splitBasicBlock(
- NewReturnBlock->getFirstNonPHI()->getIterator());
- BasicBlock::iterator I = PreReturn->begin();
- Instruction *Ins = &NewReturnBlock->front();
- SmallVector<Instruction *, 4> DeadPhis;
- while (I != PreReturn->end()) {
- PHINode *OldPhi = dyn_cast<PHINode>(I);
- if (!OldPhi)
- break;
-
- PHINode *RetPhi =
- PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "", Ins);
- OldPhi->replaceAllUsesWith(RetPhi);
- Ins = NewReturnBlock->getFirstNonPHI();
+ ClonedOI->ReturnBlock = ClonedOI->ReturnBlock->splitBasicBlock(
+ ClonedOI->ReturnBlock->getFirstNonPHI()->getIterator());
+ BasicBlock::iterator I = PreReturn->begin();
+ Instruction *Ins = &ClonedOI->ReturnBlock->front();
+ SmallVector<Instruction *, 4> DeadPhis;
+ while (I != PreReturn->end()) {
+ PHINode *OldPhi = dyn_cast<PHINode>(I);
+ if (!OldPhi)
+ break;
- RetPhi->addIncoming(&*I, PreReturn);
- for (BasicBlock *E : OI->ReturnBlockPreds) {
- BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
- RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(NewE), NewE);
- OldPhi->removeIncomingValue(NewE);
- }
+ PHINode *RetPhi =
+ PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "", Ins);
+ OldPhi->replaceAllUsesWith(RetPhi);
+ Ins = ClonedOI->ReturnBlock->getFirstNonPHI();
- // After incoming values splitting, the old phi may become trivial.
- // Keeping the trivial phi can introduce definition inside the outline
- // region which is live-out, causing necessary overhead (load, store
- // arg passing etc).
- if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
- OldPhi->replaceAllUsesWith(OldPhiVal);
- DeadPhis.push_back(OldPhi);
- }
-
- ++I;
+ RetPhi->addIncoming(&*I, PreReturn);
+ for (BasicBlock *E : ClonedOI->ReturnBlockPreds) {
+ RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(E), E);
+ OldPhi->removeIncomingValue(E);
}
+ // After incoming values splitting, the old phi may become trivial.
+ // Keeping the trivial phi can introduce definition inside the outline
+ // region which is live-out, causing necessary overhead (load, store
+ // arg passing etc).
+ if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
+ OldPhi->replaceAllUsesWith(OldPhiVal);
+ DeadPhis.push_back(OldPhi);
+ }
+ ++I;
+ }
for (auto *DP : DeadPhis)
DP->eraseFromParent();
- for (auto E : OI->ReturnBlockPreds) {
- BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
- NewE->getTerminator()->replaceUsesOfWith(PreReturn, NewReturnBlock);
+ for (auto E : ClonedOI->ReturnBlockPreds) {
+ E->getTerminator()->replaceUsesOfWith(PreReturn, ClonedOI->ReturnBlock);
}
- }
+}
+Function *PartialInlinerImpl::FunctionCloner::doFunctionOutlining() {
// Returns true if the block is to be partial inlined into the caller
// (i.e. not to be extracted to the out of line function)
- auto ToBeInlined = [&](BasicBlock *BB) {
- return BB == NewReturnBlock || NewEntries.count(BB);
+ auto ToBeInlined = [&, this](BasicBlock *BB) {
+ return BB == ClonedOI->ReturnBlock ||
+ (std::find(ClonedOI->Entries.begin(), ClonedOI->Entries.end(), BB) !=
+ ClonedOI->Entries.end());
};
+
// Gather up the blocks that we're going to extract.
std::vector<BasicBlock *> ToExtract;
- ToExtract.push_back(NewNonReturnBlock);
- for (BasicBlock &BB : *DuplicateFunction)
- if (!ToBeInlined(&BB) && &BB != NewNonReturnBlock)
+ ToExtract.push_back(ClonedOI->NonReturnBlock);
+ OutlinedRegionCost +=
+ PartialInlinerImpl::computeBBInlineCost(ClonedOI->NonReturnBlock);
+ for (BasicBlock &BB : *ClonedFunc)
+ if (!ToBeInlined(&BB) && &BB != ClonedOI->NonReturnBlock) {
ToExtract.push_back(&BB);
+ // FIXME: the code extractor may hoist/sink more code
+ // into the outlined function which may make the outlining
+ // overhead (the difference of the outlined function cost
+ // and OutliningRegionCost) look larger.
+ OutlinedRegionCost += computeBBInlineCost(&BB);
+ }
// The CodeExtractor needs a dominator tree.
DominatorTree DT;
- DT.recalculate(*DuplicateFunction);
+ DT.recalculate(*ClonedFunc);
// Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo.
LoopInfo LI(DT);
- BranchProbabilityInfo BPI(*DuplicateFunction, LI);
- BlockFrequencyInfo BFI(*DuplicateFunction, BPI, LI);
+ BranchProbabilityInfo BPI(*ClonedFunc, LI);
+ ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, LI));
// Extract the body of the if.
- Function *OutlinedFunction =
- CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false, &BFI, &BPI)
- .extractCodeRegion();
+ OutlinedFunc = CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false,
+ ClonedFuncBFI.get(), &BPI)
+ .extractCodeRegion();
+
+ if (OutlinedFunc) {
+ OutliningCallBB = PartialInlinerImpl::getOneCallSiteTo(OutlinedFunc)
+ .getInstruction()
+ ->getParent();
+ assert(OutliningCallBB->getParent() == ClonedFunc);
+ }
- bool AnyInline =
- tryPartialInline(DuplicateFunction, F, OI.get(), OutlinedFunction, &BFI);
+ return OutlinedFunc;
+}
+PartialInlinerImpl::FunctionCloner::~FunctionCloner() {
// Ditch the duplicate, since we're done with it, and rewrite all remaining
// users (function pointers, etc.) back to the original function.
- DuplicateFunction->replaceAllUsesWith(F);
- DuplicateFunction->eraseFromParent();
+ ClonedFunc->replaceAllUsesWith(OrigFunc);
+ ClonedFunc->eraseFromParent();
+ if (!IsFunctionInlined) {
+ // Remove the function that is speculatively created if there is no
+ // reference.
+ if (OutlinedFunc)
+ OutlinedFunc->eraseFromParent();
+ }
+}
+
+Function *PartialInlinerImpl::unswitchFunction(Function *F) {
+
+ if (F->hasAddressTaken())
+ return nullptr;
+
+ // Let inliner handle it
+ if (F->hasFnAttribute(Attribute::AlwaysInline))
+ return nullptr;
+
+ if (F->hasFnAttribute(Attribute::NoInline))
+ return nullptr;
+
+ if (PSI->isFunctionEntryCold(F))
+ return nullptr;
+
+ if (F->user_begin() == F->user_end())
+ return nullptr;
+
+ std::unique_ptr<FunctionOutliningInfo> OI = computeOutliningInfo(F);
+
+ if (!OI)
+ return nullptr;
+
+ FunctionCloner Cloner(F, OI.get());
+ Cloner.NormalizeReturnBlock();
+ Function *OutlinedFunction = Cloner.doFunctionOutlining();
+
+ bool AnyInline = tryPartialInline(Cloner);
if (AnyInline)
return OutlinedFunction;
- // Remove the function that is speculatively created:
- if (OutlinedFunction)
- OutlinedFunction->eraseFromParent();
-
return nullptr;
}
-bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction,
- Function *F,
- FunctionOutliningInfo *OI,
- Function *OutlinedFunction,
- BlockFrequencyInfo *CalleeBFI) {
- if (OutlinedFunction == nullptr)
- return false;
-
+bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) {
int NonWeightedRcost;
int SizeCost;
- int OutlinedRegionSizeCost;
- auto OutliningCallBB =
- getOneCallSiteTo(OutlinedFunction).getInstruction()->getParent();
+ if (Cloner.OutlinedFunc == nullptr)
+ return false;
+
+ std::tie(SizeCost, NonWeightedRcost) = computeOutliningCosts(Cloner);
- std::tie(SizeCost, NonWeightedRcost, OutlinedRegionSizeCost) =
- computeOutliningCosts(F, OI, OutlinedFunction, OutliningCallBB);
+ auto RelativeToEntryFreq = getOutliningCallBBRelativeFreq(Cloner);
+ auto WeightedRcost = BlockFrequency(NonWeightedRcost) * RelativeToEntryFreq;
// The call sequence to the outlined function is larger than the original
// outlined region size, it does not increase the chances of inlining
- // 'F' with outlining (The inliner usies the size increase to model the
- // the cost of inlining a callee).
- if (!SkipCostAnalysis && OutlinedRegionSizeCost < SizeCost) {
- OptimizationRemarkEmitter ORE(F);
+ // the function with outlining (The inliner usies the size increase to
+ // model the cost of inlining a callee).
+ if (!SkipCostAnalysis && Cloner.OutlinedRegionCost < SizeCost) {
+ OptimizationRemarkEmitter ORE(Cloner.OrigFunc);
DebugLoc DLoc;
BasicBlock *Block;
- std::tie(DLoc, Block) = getOneDebugLoc(DuplicateFunction);
+ std::tie(DLoc, Block) = getOneDebugLoc(Cloner.ClonedFunc);
ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall",
DLoc, Block)
- << ore::NV("Function", F)
+ << ore::NV("Function", Cloner.OrigFunc)
<< " not partially inlined into callers (Original Size = "
- << ore::NV("OutlinedRegionOriginalSize", OutlinedRegionSizeCost)
+ << ore::NV("OutlinedRegionOriginalSize", Cloner.OutlinedRegionCost)
<< ", Size of call sequence to outlined function = "
<< ore::NV("NewSize", SizeCost) << ")");
return false;
}
- assert(F->user_begin() == F->user_end() &&
+ assert(Cloner.OrigFunc->user_begin() == Cloner.OrigFunc->user_end() &&
"F's users should all be replaced!");
- std::vector<User *> Users(DuplicateFunction->user_begin(),
- DuplicateFunction->user_end());
+
+ std::vector<User *> Users(Cloner.ClonedFunc->user_begin(),
+ Cloner.ClonedFunc->user_end());
DenseMap<User *, uint64_t> CallSiteToProfCountMap;
- if (F->getEntryCount())
- computeCallsiteToProfCountMap(DuplicateFunction, CallSiteToProfCountMap);
+ if (Cloner.OrigFunc->getEntryCount())
+ computeCallsiteToProfCountMap(Cloner.ClonedFunc, CallSiteToProfCountMap);
- auto CalleeEntryCount = F->getEntryCount();
+ auto CalleeEntryCount = Cloner.OrigFunc->getEntryCount();
uint64_t CalleeEntryCountV = (CalleeEntryCount ? *CalleeEntryCount : 0);
+
bool AnyInline = false;
for (User *User : Users) {
CallSite CS = getCallSite(User);
@@ -854,13 +884,12 @@ bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction,
OptimizationRemarkEmitter ORE(CS.getCaller());
- if (!shouldPartialInline(CS, F, OI, CalleeBFI, OutliningCallBB,
- NonWeightedRcost, ORE))
+ if (!shouldPartialInline(CS, Cloner, WeightedRcost, ORE))
continue;
ORE.emit(
OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", CS.getInstruction())
- << ore::NV("Callee", F) << " partially inlined into "
+ << ore::NV("Callee", Cloner.OrigFunc) << " partially inlined into "
<< ore::NV("Caller", CS.getCaller()));
InlineFunctionInfo IFI(nullptr, GetAssumptionCache, PSI);
@@ -878,8 +907,11 @@ bool PartialInlinerImpl::tryPartialInline(Function *DuplicateFunction,
NumPartialInlined++;
}
- if (AnyInline && CalleeEntryCount)
- F->setEntryCount(CalleeEntryCountV);
+ if (AnyInline) {
+ Cloner.IsFunctionInlined = true;
+ if (CalleeEntryCount)
+ Cloner.OrigFunc->setEntryCount(CalleeEntryCountV);
+ }
return AnyInline;
}
diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp
index 16fba32e9805..4bc64ab698ff 100644
--- a/lib/Transforms/IPO/PassManagerBuilder.cpp
+++ b/lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -141,6 +141,10 @@ static cl::opt<int> PreInlineThreshold(
cl::desc("Control the amount of inlining in pre-instrumentation inliner "
"(default = 75)"));
+static cl::opt<bool> EnableEarlyCSEMemSSA(
+ "enable-earlycse-memssa", cl::init(false), cl::Hidden,
+ cl::desc("Enable the EarlyCSE w/ MemorySSA pass (default = off)"));
+
static cl::opt<bool> EnableGVNHoist(
"enable-gvn-hoist", cl::init(false), cl::Hidden,
cl::desc("Enable the GVN hoisting pass (default = off)"));
@@ -308,7 +312,7 @@ void PassManagerBuilder::addFunctionSimplificationPasses(
// Start of function pass.
// Break up aggregate allocas, using SSAUpdater.
MPM.add(createSROAPass());
- MPM.add(createEarlyCSEPass()); // Catch trivial redundancies
+ MPM.add(createEarlyCSEPass(EnableEarlyCSEMemSSA)); // Catch trivial redundancies
if (EnableGVNHoist)
MPM.add(createGVNHoistPass());
if (EnableGVNSink) {
diff --git a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
index a7bcc7cc5532..802f470ffe1f 100644
--- a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
+++ b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
@@ -32,7 +32,8 @@ namespace {
// Promote each local-linkage entity defined by ExportM and used by ImportM by
// changing visibility and appending the given ModuleId.
-void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId) {
+void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
+ SetVector<GlobalValue *> &PromoteExtra) {
DenseMap<const Comdat *, Comdat *> RenamedComdats;
for (auto &ExportGV : ExportM.global_values()) {
if (!ExportGV.hasLocalLinkage())
@@ -40,7 +41,7 @@ void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId) {
auto Name = ExportGV.getName();
GlobalValue *ImportGV = ImportM.getNamedValue(Name);
- if (!ImportGV || ImportGV->use_empty())
+ if ((!ImportGV || ImportGV->use_empty()) && !PromoteExtra.count(&ExportGV))
continue;
std::string NewName = (Name + ModuleId).str();
@@ -53,8 +54,10 @@ void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId) {
ExportGV.setLinkage(GlobalValue::ExternalLinkage);
ExportGV.setVisibility(GlobalValue::HiddenVisibility);
- ImportGV->setName(NewName);
- ImportGV->setVisibility(GlobalValue::HiddenVisibility);
+ if (ImportGV) {
+ ImportGV->setName(NewName);
+ ImportGV->setVisibility(GlobalValue::HiddenVisibility);
+ }
}
if (!RenamedComdats.empty())
@@ -296,6 +299,11 @@ void splitAndWriteThinLTOBitcode(
F.setComdat(nullptr);
}
+ SetVector<GlobalValue *> CfiFunctions;
+ for (auto &F : M)
+ if ((!F.hasLocalLinkage() || F.hasAddressTaken()) && HasTypeMetadata(&F))
+ CfiFunctions.insert(&F);
+
// Remove all globals with type metadata, globals with comdats that live in
// MergedM, and aliases pointing to such globals from the thin LTO module.
filterModule(&M, [&](const GlobalValue *GV) {
@@ -308,11 +316,39 @@ void splitAndWriteThinLTOBitcode(
return true;
});
- promoteInternals(*MergedM, M, ModuleId);
- promoteInternals(M, *MergedM, ModuleId);
+ promoteInternals(*MergedM, M, ModuleId, CfiFunctions);
+ promoteInternals(M, *MergedM, ModuleId, CfiFunctions);
+
+ SmallVector<MDNode *, 8> CfiFunctionMDs;
+ for (auto V : CfiFunctions) {
+ Function &F = *cast<Function>(V);
+ SmallVector<MDNode *, 2> Types;
+ F.getMetadata(LLVMContext::MD_type, Types);
+
+ auto &Ctx = MergedM->getContext();
+ SmallVector<Metadata *, 4> Elts;
+ Elts.push_back(MDString::get(Ctx, F.getName()));
+ CfiFunctionLinkage Linkage;
+ if (!F.isDeclarationForLinker())
+ Linkage = CFL_Definition;
+ else if (F.isWeakForLinker())
+ Linkage = CFL_WeakDeclaration;
+ else
+ Linkage = CFL_Declaration;
+ Elts.push_back(ConstantAsMetadata::get(
+ llvm::ConstantInt::get(Type::getInt8Ty(Ctx), Linkage)));
+ for (auto Type : Types)
+ Elts.push_back(Type);
+ CfiFunctionMDs.push_back(MDTuple::get(Ctx, Elts));
+ }
- simplifyExternals(*MergedM);
+ if(!CfiFunctionMDs.empty()) {
+ NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("cfi.functions");
+ for (auto MD : CfiFunctionMDs)
+ NMD->addOperand(MD);
+ }
+ simplifyExternals(*MergedM);
// FIXME: Try to re-use BSI and PFI from the original module here.
ProfileSummaryInfo PSI(M);
diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 4fe3225a2172..a881bda5ba98 100644
--- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -763,8 +763,54 @@ foldAndOrOfEqualityCmpsWithConstants(ICmpInst *LHS, ICmpInst *RHS,
return nullptr;
}
+// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
+// Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
+Value *InstCombiner::foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS,
+ bool JoinedByAnd,
+ Instruction &CxtI) {
+ ICmpInst::Predicate Pred = LHS->getPredicate();
+ if (Pred != RHS->getPredicate())
+ return nullptr;
+ if (JoinedByAnd && Pred != ICmpInst::ICMP_NE)
+ return nullptr;
+ if (!JoinedByAnd && Pred != ICmpInst::ICMP_EQ)
+ return nullptr;
+
+ // TODO support vector splats
+ ConstantInt *LHSC = dyn_cast<ConstantInt>(LHS->getOperand(1));
+ ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS->getOperand(1));
+ if (!LHSC || !RHSC || !LHSC->isZero() || !RHSC->isZero())
+ return nullptr;
+
+ Value *A, *B, *C, *D;
+ if (match(LHS->getOperand(0), m_And(m_Value(A), m_Value(B))) &&
+ match(RHS->getOperand(0), m_And(m_Value(C), m_Value(D)))) {
+ if (A == D || B == D)
+ std::swap(C, D);
+ if (B == C)
+ std::swap(A, B);
+
+ if (A == C &&
+ isKnownToBeAPowerOfTwo(B, false, 0, &CxtI) &&
+ isKnownToBeAPowerOfTwo(D, false, 0, &CxtI)) {
+ Value *Mask = Builder->CreateOr(B, D);
+ Value *Masked = Builder->CreateAnd(A, Mask);
+ auto NewPred = JoinedByAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
+ return Builder->CreateICmp(NewPred, Masked, Mask);
+ }
+ }
+
+ return nullptr;
+}
+
/// Fold (icmp)&(icmp) if possible.
-Value *InstCombiner::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
+Value *InstCombiner::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS,
+ Instruction &CxtI) {
+ // Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
+ // if K1 and K2 are a one-bit mask.
+ if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, true, CxtI))
+ return V;
+
ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
// (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B)
@@ -1127,8 +1173,8 @@ Instruction *InstCombiner::foldCastedBitwiseLogic(BinaryOperator &I) {
ICmpInst *ICmp0 = dyn_cast<ICmpInst>(Cast0Src);
ICmpInst *ICmp1 = dyn_cast<ICmpInst>(Cast1Src);
if (ICmp0 && ICmp1) {
- Value *Res = LogicOpc == Instruction::And ? foldAndOfICmps(ICmp0, ICmp1)
- : foldOrOfICmps(ICmp0, ICmp1, &I);
+ Value *Res = LogicOpc == Instruction::And ? foldAndOfICmps(ICmp0, ICmp1, I)
+ : foldOrOfICmps(ICmp0, ICmp1, I);
if (Res)
return CastInst::Create(CastOpcode, Res, DestTy);
return nullptr;
@@ -1426,7 +1472,7 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
if (LHS && RHS)
- if (Value *Res = foldAndOfICmps(LHS, RHS))
+ if (Value *Res = foldAndOfICmps(LHS, RHS, I))
return replaceInstUsesWith(I, Res);
// TODO: Make this recursive; it's a little tricky because an arbitrary
@@ -1434,18 +1480,18 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
Value *X, *Y;
if (LHS && match(Op1, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
- if (Value *Res = foldAndOfICmps(LHS, Cmp))
+ if (Value *Res = foldAndOfICmps(LHS, Cmp, I))
return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
- if (Value *Res = foldAndOfICmps(LHS, Cmp))
+ if (Value *Res = foldAndOfICmps(LHS, Cmp, I))
return replaceInstUsesWith(I, Builder->CreateAnd(Res, X));
}
if (RHS && match(Op0, m_OneUse(m_And(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
- if (Value *Res = foldAndOfICmps(Cmp, RHS))
+ if (Value *Res = foldAndOfICmps(Cmp, RHS, I))
return replaceInstUsesWith(I, Builder->CreateAnd(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
- if (Value *Res = foldAndOfICmps(Cmp, RHS))
+ if (Value *Res = foldAndOfICmps(Cmp, RHS, I))
return replaceInstUsesWith(I, Builder->CreateAnd(Res, X));
}
}
@@ -1591,41 +1637,16 @@ static Value *matchSelectFromAndOr(Value *A, Value *C, Value *B, Value *D,
/// Fold (icmp)|(icmp) if possible.
Value *InstCombiner::foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
- Instruction *CxtI) {
- ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
-
+ Instruction &CxtI) {
// Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
// if K1 and K2 are a one-bit mask.
- ConstantInt *LHSC = dyn_cast<ConstantInt>(LHS->getOperand(1));
- ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS->getOperand(1));
+ if (Value *V = foldAndOrOfICmpsOfAndWithPow2(LHS, RHS, false, CxtI))
+ return V;
- if (LHS->getPredicate() == ICmpInst::ICMP_EQ && LHSC && LHSC->isZero() &&
- RHS->getPredicate() == ICmpInst::ICMP_EQ && RHSC && RHSC->isZero()) {
-
- BinaryOperator *LAnd = dyn_cast<BinaryOperator>(LHS->getOperand(0));
- BinaryOperator *RAnd = dyn_cast<BinaryOperator>(RHS->getOperand(0));
- if (LAnd && RAnd && LAnd->hasOneUse() && RHS->hasOneUse() &&
- LAnd->getOpcode() == Instruction::And &&
- RAnd->getOpcode() == Instruction::And) {
-
- Value *Mask = nullptr;
- Value *Masked = nullptr;
- if (LAnd->getOperand(0) == RAnd->getOperand(0) &&
- isKnownToBeAPowerOfTwo(LAnd->getOperand(1), false, 0, CxtI) &&
- isKnownToBeAPowerOfTwo(RAnd->getOperand(1), false, 0, CxtI)) {
- Mask = Builder->CreateOr(LAnd->getOperand(1), RAnd->getOperand(1));
- Masked = Builder->CreateAnd(LAnd->getOperand(0), Mask);
- } else if (LAnd->getOperand(1) == RAnd->getOperand(1) &&
- isKnownToBeAPowerOfTwo(LAnd->getOperand(0), false, 0, CxtI) &&
- isKnownToBeAPowerOfTwo(RAnd->getOperand(0), false, 0, CxtI)) {
- Mask = Builder->CreateOr(LAnd->getOperand(0), RAnd->getOperand(0));
- Masked = Builder->CreateAnd(LAnd->getOperand(1), Mask);
- }
+ ICmpInst::Predicate PredL = LHS->getPredicate(), PredR = RHS->getPredicate();
- if (Masked)
- return Builder->CreateICmp(ICmpInst::ICMP_NE, Masked, Mask);
- }
- }
+ ConstantInt *LHSC = dyn_cast<ConstantInt>(LHS->getOperand(1));
+ ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS->getOperand(1));
// Fold (icmp ult/ule (A + C1), C3) | (icmp ult/ule (A + C2), C3)
// --> (icmp ult/ule ((A & ~(C1 ^ C2)) + max(C1, C2)), C3)
@@ -2117,12 +2138,16 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
}
// (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C
+ // FIXME: The two hasOneUse calls here are the same call, maybe we were
+ // supposed to check Op1->operand(0)?
if (match(Op0, m_Xor(m_Value(A), m_Value(B))))
if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A))))
if (Op1->hasOneUse() || cast<BinaryOperator>(Op1)->hasOneUse())
return BinaryOperator::CreateOr(Op0, C);
// ((A ^ C) ^ B) | (B ^ A) -> (B ^ A) | C
+ // FIXME: The two hasOneUse calls here are the same call, maybe we were
+ // supposed to check Op0->operand(0)?
if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B))))
if (match(Op1, m_Xor(m_Specific(B), m_Specific(A))))
if (Op0->hasOneUse() || cast<BinaryOperator>(Op0)->hasOneUse())
@@ -2194,7 +2219,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
if (LHS && RHS)
- if (Value *Res = foldOrOfICmps(LHS, RHS, &I))
+ if (Value *Res = foldOrOfICmps(LHS, RHS, I))
return replaceInstUsesWith(I, Res);
// TODO: Make this recursive; it's a little tricky because an arbitrary
@@ -2202,18 +2227,18 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
Value *X, *Y;
if (LHS && match(Op1, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
- if (Value *Res = foldOrOfICmps(LHS, Cmp, &I))
+ if (Value *Res = foldOrOfICmps(LHS, Cmp, I))
return replaceInstUsesWith(I, Builder->CreateOr(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
- if (Value *Res = foldOrOfICmps(LHS, Cmp, &I))
+ if (Value *Res = foldOrOfICmps(LHS, Cmp, I))
return replaceInstUsesWith(I, Builder->CreateOr(Res, X));
}
if (RHS && match(Op0, m_OneUse(m_Or(m_Value(X), m_Value(Y))))) {
if (auto *Cmp = dyn_cast<ICmpInst>(X))
- if (Value *Res = foldOrOfICmps(Cmp, RHS, &I))
+ if (Value *Res = foldOrOfICmps(Cmp, RHS, I))
return replaceInstUsesWith(I, Builder->CreateOr(Res, Y));
if (auto *Cmp = dyn_cast<ICmpInst>(Y))
- if (Value *Res = foldOrOfICmps(Cmp, RHS, &I))
+ if (Value *Res = foldOrOfICmps(Cmp, RHS, I))
return replaceInstUsesWith(I, Builder->CreateOr(Res, X));
}
}
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index d29ed49eca0b..c0830a5d2112 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -94,75 +94,80 @@ static Constant *getNegativeIsTrueBoolVec(ConstantDataVector *V) {
return ConstantVector::get(BoolVec);
}
-Instruction *
-InstCombiner::SimplifyElementAtomicMemCpy(ElementAtomicMemCpyInst *AMI) {
+Instruction *InstCombiner::SimplifyElementUnorderedAtomicMemCpy(
+ ElementUnorderedAtomicMemCpyInst *AMI) {
// Try to unfold this intrinsic into sequence of explicit atomic loads and
// stores.
// First check that number of elements is compile time constant.
- auto *NumElementsCI = dyn_cast<ConstantInt>(AMI->getNumElements());
- if (!NumElementsCI)
+ auto *LengthCI = dyn_cast<ConstantInt>(AMI->getLength());
+ if (!LengthCI)
return nullptr;
// Check that there are not too many elements.
- uint64_t NumElements = NumElementsCI->getZExtValue();
+ uint64_t LengthInBytes = LengthCI->getZExtValue();
+ uint32_t ElementSizeInBytes = AMI->getElementSizeInBytes();
+ uint64_t NumElements = LengthInBytes / ElementSizeInBytes;
if (NumElements >= UnfoldElementAtomicMemcpyMaxElements)
return nullptr;
- // Don't unfold into illegal integers
- uint64_t ElementSizeInBytes = AMI->getElementSizeInBytes() * 8;
- if (!getDataLayout().isLegalInteger(ElementSizeInBytes))
- return nullptr;
+ // Only expand if there are elements to copy.
+ if (NumElements > 0) {
+ // Don't unfold into illegal integers
+ uint64_t ElementSizeInBits = ElementSizeInBytes * 8;
+ if (!getDataLayout().isLegalInteger(ElementSizeInBits))
+ return nullptr;
- // Cast source and destination to the correct type. Intrinsic input arguments
- // are usually represented as i8*.
- // Often operands will be explicitly casted to i8* and we can just strip
- // those casts instead of inserting new ones. However it's easier to rely on
- // other InstCombine rules which will cover trivial cases anyway.
- Value *Src = AMI->getRawSource();
- Value *Dst = AMI->getRawDest();
- Type *ElementPointerType = Type::getIntNPtrTy(
- AMI->getContext(), ElementSizeInBytes, Src->getType()->getPointerAddressSpace());
-
- Value *SrcCasted = Builder->CreatePointerCast(Src, ElementPointerType,
- "memcpy_unfold.src_casted");
- Value *DstCasted = Builder->CreatePointerCast(Dst, ElementPointerType,
- "memcpy_unfold.dst_casted");
-
- for (uint64_t i = 0; i < NumElements; ++i) {
- // Get current element addresses
- ConstantInt *ElementIdxCI =
- ConstantInt::get(AMI->getContext(), APInt(64, i));
- Value *SrcElementAddr =
- Builder->CreateGEP(SrcCasted, ElementIdxCI, "memcpy_unfold.src_addr");
- Value *DstElementAddr =
- Builder->CreateGEP(DstCasted, ElementIdxCI, "memcpy_unfold.dst_addr");
-
- // Load from the source. Transfer alignment information and mark load as
- // unordered atomic.
- LoadInst *Load = Builder->CreateLoad(SrcElementAddr, "memcpy_unfold.val");
- Load->setOrdering(AtomicOrdering::Unordered);
- // We know alignment of the first element. It is also guaranteed by the
- // verifier that element size is less or equal than first element alignment
- // and both of this values are powers of two.
- // This means that all subsequent accesses are at least element size
- // aligned.
- // TODO: We can infer better alignment but there is no evidence that this
- // will matter.
- Load->setAlignment(i == 0 ? AMI->getSrcAlignment()
- : AMI->getElementSizeInBytes());
- Load->setDebugLoc(AMI->getDebugLoc());
-
- // Store loaded value via unordered atomic store.
- StoreInst *Store = Builder->CreateStore(Load, DstElementAddr);
- Store->setOrdering(AtomicOrdering::Unordered);
- Store->setAlignment(i == 0 ? AMI->getDstAlignment()
- : AMI->getElementSizeInBytes());
- Store->setDebugLoc(AMI->getDebugLoc());
+ // Cast source and destination to the correct type. Intrinsic input
+ // arguments are usually represented as i8*. Often operands will be
+ // explicitly casted to i8* and we can just strip those casts instead of
+ // inserting new ones. However it's easier to rely on other InstCombine
+ // rules which will cover trivial cases anyway.
+ Value *Src = AMI->getRawSource();
+ Value *Dst = AMI->getRawDest();
+ Type *ElementPointerType =
+ Type::getIntNPtrTy(AMI->getContext(), ElementSizeInBits,
+ Src->getType()->getPointerAddressSpace());
+
+ Value *SrcCasted = Builder->CreatePointerCast(Src, ElementPointerType,
+ "memcpy_unfold.src_casted");
+ Value *DstCasted = Builder->CreatePointerCast(Dst, ElementPointerType,
+ "memcpy_unfold.dst_casted");
+
+ for (uint64_t i = 0; i < NumElements; ++i) {
+ // Get current element addresses
+ ConstantInt *ElementIdxCI =
+ ConstantInt::get(AMI->getContext(), APInt(64, i));
+ Value *SrcElementAddr =
+ Builder->CreateGEP(SrcCasted, ElementIdxCI, "memcpy_unfold.src_addr");
+ Value *DstElementAddr =
+ Builder->CreateGEP(DstCasted, ElementIdxCI, "memcpy_unfold.dst_addr");
+
+ // Load from the source. Transfer alignment information and mark load as
+ // unordered atomic.
+ LoadInst *Load = Builder->CreateLoad(SrcElementAddr, "memcpy_unfold.val");
+ Load->setOrdering(AtomicOrdering::Unordered);
+ // We know alignment of the first element. It is also guaranteed by the
+ // verifier that element size is less or equal than first element
+ // alignment and both of this values are powers of two. This means that
+ // all subsequent accesses are at least element size aligned.
+ // TODO: We can infer better alignment but there is no evidence that this
+ // will matter.
+ Load->setAlignment(i == 0 ? AMI->getParamAlignment(1)
+ : ElementSizeInBytes);
+ Load->setDebugLoc(AMI->getDebugLoc());
+
+ // Store loaded value via unordered atomic store.
+ StoreInst *Store = Builder->CreateStore(Load, DstElementAddr);
+ Store->setOrdering(AtomicOrdering::Unordered);
+ Store->setAlignment(i == 0 ? AMI->getParamAlignment(0)
+ : ElementSizeInBytes);
+ Store->setDebugLoc(AMI->getDebugLoc());
+ }
}
// Set the number of elements of the copy to 0, it will be deleted on the
// next iteration.
- AMI->setNumElements(Constant::getNullValue(NumElementsCI->getType()));
+ AMI->setLength(Constant::getNullValue(LengthCI->getType()));
return AMI;
}
@@ -1888,12 +1893,12 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
if (Changed) return II;
}
- if (auto *AMI = dyn_cast<ElementAtomicMemCpyInst>(II)) {
- if (Constant *C = dyn_cast<Constant>(AMI->getNumElements()))
+ if (auto *AMI = dyn_cast<ElementUnorderedAtomicMemCpyInst>(II)) {
+ if (Constant *C = dyn_cast<Constant>(AMI->getLength()))
if (C->isNullValue())
return eraseInstFromFunction(*AMI);
- if (Instruction *I = SimplifyElementAtomicMemCpy(AMI))
+ if (Instruction *I = SimplifyElementUnorderedAtomicMemCpy(AMI))
return I;
}
diff --git a/lib/Transforms/InstCombine/InstCombineInternal.h b/lib/Transforms/InstCombine/InstCombineInternal.h
index fd0a64a5bbb5..1a7db146df42 100644
--- a/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -447,12 +447,14 @@ private:
Instruction::CastOps isEliminableCastPair(const CastInst *CI1,
const CastInst *CI2);
- Value *foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS);
+ Value *foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction &CxtI);
Value *foldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
- Value *foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction *CxtI);
+ Value *foldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS, Instruction &CxtI);
Value *foldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS);
Value *foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS);
+ Value *foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS,
+ bool JoinedByAnd, Instruction &CxtI);
public:
/// \brief Inserts an instruction \p New before instruction \p Old
///
@@ -724,7 +726,8 @@ private:
Instruction *MatchBSwap(BinaryOperator &I);
bool SimplifyStoreAtEndOfBlock(StoreInst &SI);
- Instruction *SimplifyElementAtomicMemCpy(ElementAtomicMemCpyInst *AMI);
+ Instruction *
+ SimplifyElementUnorderedAtomicMemCpy(ElementUnorderedAtomicMemCpyInst *AMI);
Instruction *SimplifyMemTransfer(MemIntrinsic *MI);
Instruction *SimplifyMemSet(MemSetInst *MI);
diff --git a/lib/Transforms/InstCombine/InstCombineShifts.cpp b/lib/Transforms/InstCombine/InstCombineShifts.cpp
index 3f2ddcacce2b..8cec865c6422 100644
--- a/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -682,11 +682,11 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
}
- if (match(Op0, m_SExt(m_Value(X)))) {
+ if (match(Op0, m_SExt(m_Value(X))) &&
+ (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
// Are we moving the sign bit to the low bit and widening with high zeros?
unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits();
- if (ShAmt == BitWidth - 1 &&
- (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
+ if (ShAmt == BitWidth - 1) {
// lshr (sext i1 X to iN), N-1 --> zext X to iN
if (SrcTyBitWidth == 1)
return new ZExtInst(X, Ty);
@@ -698,7 +698,13 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
}
}
- // TODO: Convert to ashr+zext if the shift equals the extension amount.
+ // lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN
+ if (ShAmt == BitWidth - SrcTyBitWidth && Op0->hasOneUse()) {
+ // The new shift amount can't be more than the narrow source type.
+ unsigned NewShAmt = std::min(ShAmt, SrcTyBitWidth - 1);
+ Value *AShr = Builder->CreateAShr(X, NewShAmt);
+ return new ZExtInst(AShr, Ty);
+ }
}
if (match(Op0, m_LShr(m_Value(X), m_APInt(ShOp1)))) {
diff --git a/lib/Transforms/Instrumentation/CMakeLists.txt b/lib/Transforms/Instrumentation/CMakeLists.txt
index 7ff69b9eb7f4..f2806e278e6e 100644
--- a/lib/Transforms/Instrumentation/CMakeLists.txt
+++ b/lib/Transforms/Instrumentation/CMakeLists.txt
@@ -8,6 +8,7 @@ add_llvm_library(LLVMInstrumentation
Instrumentation.cpp
InstrProfiling.cpp
PGOInstrumentation.cpp
+ PGOMemOPSizeOpt.cpp
SanitizerCoverage.cpp
ThreadSanitizer.cpp
EfficiencySanitizer.cpp
diff --git a/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp b/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
index 96027bc3d0a9..0d308810009d 100644
--- a/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
+++ b/lib/Transforms/Instrumentation/IndirectCallPromotion.cpp
@@ -56,8 +56,6 @@ using namespace llvm;
STATISTIC(NumOfPGOICallPromotion, "Number of indirect call promotions.");
STATISTIC(NumOfPGOICallsites, "Number of indirect call candidate sites.");
-STATISTIC(NumOfPGOMemOPOpt, "Number of memop intrinsics optimized.");
-STATISTIC(NumOfPGOMemOPAnnotate, "Number of memop intrinsics annotated.");
// Command line option to disable indirect-call promotion with the default as
// false. This is for debug purpose.
@@ -111,44 +109,6 @@ static cl::opt<bool>
ICPDUMPAFTER("icp-dumpafter", cl::init(false), cl::Hidden,
cl::desc("Dump IR after transformation happens"));
-// The minimum call count to optimize memory intrinsic calls.
-static cl::opt<unsigned>
- MemOPCountThreshold("pgo-memop-count-threshold", cl::Hidden, cl::ZeroOrMore,
- cl::init(1000),
- cl::desc("The minimum count to optimize memory "
- "intrinsic calls"));
-
-// Command line option to disable memory intrinsic optimization. The default is
-// false. This is for debug purpose.
-static cl::opt<bool> DisableMemOPOPT("disable-memop-opt", cl::init(false),
- cl::Hidden, cl::desc("Disable optimize"));
-
-// The percent threshold to optimize memory intrinsic calls.
-static cl::opt<unsigned>
- MemOPPercentThreshold("pgo-memop-percent-threshold", cl::init(40),
- cl::Hidden, cl::ZeroOrMore,
- cl::desc("The percentage threshold for the "
- "memory intrinsic calls optimization"));
-
-// Maximum number of versions for optimizing memory intrinsic call.
-static cl::opt<unsigned>
- MemOPMaxVersion("pgo-memop-max-version", cl::init(3), cl::Hidden,
- cl::ZeroOrMore,
- cl::desc("The max version for the optimized memory "
- " intrinsic calls"));
-
-// Scale the counts from the annotation using the BB count value.
-static cl::opt<bool>
- MemOPScaleCount("pgo-memop-scale-count", cl::init(true), cl::Hidden,
- cl::desc("Scale the memop size counts using the basic "
- " block count value"));
-
-// This option sets the rangge of precise profile memop sizes.
-extern cl::opt<std::string> MemOPSizeRange;
-
-// This option sets the value that groups large memop sizes
-extern cl::opt<unsigned> MemOPSizeLarge;
-
namespace {
class PGOIndirectCallPromotionLegacyPass : public ModulePass {
public:
@@ -173,24 +133,6 @@ private:
// the promoted direct call.
bool SamplePGO;
};
-
-class PGOMemOPSizeOptLegacyPass : public FunctionPass {
-public:
- static char ID;
-
- PGOMemOPSizeOptLegacyPass() : FunctionPass(ID) {
- initializePGOMemOPSizeOptLegacyPassPass(*PassRegistry::getPassRegistry());
- }
-
- StringRef getPassName() const override { return "PGOMemOPSize"; }
-
-private:
- bool runOnFunction(Function &F) override;
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.addRequired<BlockFrequencyInfoWrapperPass>();
- AU.addPreserved<GlobalsAAWrapperPass>();
- }
-};
} // end anonymous namespace
char PGOIndirectCallPromotionLegacyPass::ID = 0;
@@ -204,19 +146,6 @@ ModulePass *llvm::createPGOIndirectCallPromotionLegacyPass(bool InLTO,
return new PGOIndirectCallPromotionLegacyPass(InLTO, SamplePGO);
}
-char PGOMemOPSizeOptLegacyPass::ID = 0;
-INITIALIZE_PASS_BEGIN(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt",
- "Optimize memory intrinsic using its size value profile",
- false, false)
-INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
-INITIALIZE_PASS_END(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt",
- "Optimize memory intrinsic using its size value profile",
- false, false)
-
-FunctionPass *llvm::createPGOMemOPSizeOptLegacyPass() {
- return new PGOMemOPSizeOptLegacyPass();
-}
-
namespace {
// The class for main data structure to promote indirect calls to conditional
// direct calls.
@@ -749,285 +678,3 @@ PreservedAnalyses PGOIndirectCallPromotion::run(Module &M,
return PreservedAnalyses::none();
}
-
-namespace {
-class MemOPSizeOpt : public InstVisitor<MemOPSizeOpt> {
-public:
- MemOPSizeOpt(Function &Func, BlockFrequencyInfo &BFI)
- : Func(Func), BFI(BFI), Changed(false) {
- ValueDataArray =
- llvm::make_unique<InstrProfValueData[]>(MemOPMaxVersion + 2);
- // Get the MemOPSize range information from option MemOPSizeRange,
- getMemOPSizeRangeFromOption(MemOPSizeRange, PreciseRangeStart,
- PreciseRangeLast);
- }
- bool isChanged() const { return Changed; }
- void perform() {
- WorkList.clear();
- visit(Func);
-
- for (auto &MI : WorkList) {
- ++NumOfPGOMemOPAnnotate;
- if (perform(MI)) {
- Changed = true;
- ++NumOfPGOMemOPOpt;
- DEBUG(dbgs() << "MemOP call: " << MI->getCalledFunction()->getName()
- << "is Transformed.\n");
- }
- }
- }
-
- void visitMemIntrinsic(MemIntrinsic &MI) {
- Value *Length = MI.getLength();
- // Not perform on constant length calls.
- if (dyn_cast<ConstantInt>(Length))
- return;
- WorkList.push_back(&MI);
- }
-
-private:
- Function &Func;
- BlockFrequencyInfo &BFI;
- bool Changed;
- std::vector<MemIntrinsic *> WorkList;
- // Start of the previse range.
- int64_t PreciseRangeStart;
- // Last value of the previse range.
- int64_t PreciseRangeLast;
- // The space to read the profile annotation.
- std::unique_ptr<InstrProfValueData[]> ValueDataArray;
- bool perform(MemIntrinsic *MI);
-
- // This kind shows which group the value falls in. For PreciseValue, we have
- // the profile count for that value. LargeGroup groups the values that are in
- // range [LargeValue, +inf). NonLargeGroup groups the rest of values.
- enum MemOPSizeKind { PreciseValue, NonLargeGroup, LargeGroup };
-
- MemOPSizeKind getMemOPSizeKind(int64_t Value) const {
- if (Value == MemOPSizeLarge && MemOPSizeLarge != 0)
- return LargeGroup;
- if (Value == PreciseRangeLast + 1)
- return NonLargeGroup;
- return PreciseValue;
- }
-};
-
-static const char *getMIName(const MemIntrinsic *MI) {
- switch (MI->getIntrinsicID()) {
- case Intrinsic::memcpy:
- return "memcpy";
- case Intrinsic::memmove:
- return "memmove";
- case Intrinsic::memset:
- return "memset";
- default:
- return "unknown";
- }
-}
-
-static bool isProfitable(uint64_t Count, uint64_t TotalCount) {
- assert(Count <= TotalCount);
- if (Count < MemOPCountThreshold)
- return false;
- if (Count < TotalCount * MemOPPercentThreshold / 100)
- return false;
- return true;
-}
-
-static inline uint64_t getScaledCount(uint64_t Count, uint64_t Num,
- uint64_t Denom) {
- if (!MemOPScaleCount)
- return Count;
- bool Overflowed;
- uint64_t ScaleCount = SaturatingMultiply(Count, Num, &Overflowed);
- return ScaleCount / Denom;
-}
-
-bool MemOPSizeOpt::perform(MemIntrinsic *MI) {
- assert(MI);
- if (MI->getIntrinsicID() == Intrinsic::memmove)
- return false;
-
- uint32_t NumVals, MaxNumPromotions = MemOPMaxVersion + 2;
- uint64_t TotalCount;
- if (!getValueProfDataFromInst(*MI, IPVK_MemOPSize, MaxNumPromotions,
- ValueDataArray.get(), NumVals, TotalCount))
- return false;
-
- uint64_t ActualCount = TotalCount;
- uint64_t SavedTotalCount = TotalCount;
- if (MemOPScaleCount) {
- auto BBEdgeCount = BFI.getBlockProfileCount(MI->getParent());
- if (!BBEdgeCount)
- return false;
- ActualCount = *BBEdgeCount;
- }
-
- ArrayRef<InstrProfValueData> VDs(ValueDataArray.get(), NumVals);
- DEBUG(dbgs() << "Read one memory intrinsic profile with count " << ActualCount
- << "\n");
- DEBUG(
- for (auto &VD
- : VDs) { dbgs() << " (" << VD.Value << "," << VD.Count << ")\n"; });
-
- if (ActualCount < MemOPCountThreshold)
- return false;
- // Skip if the total value profiled count is 0, in which case we can't
- // scale up the counts properly (and there is no profitable transformation).
- if (TotalCount == 0)
- return false;
-
- TotalCount = ActualCount;
- if (MemOPScaleCount)
- DEBUG(dbgs() << "Scale counts: numerator = " << ActualCount
- << " denominator = " << SavedTotalCount << "\n");
-
- // Keeping track of the count of the default case:
- uint64_t RemainCount = TotalCount;
- SmallVector<uint64_t, 16> SizeIds;
- SmallVector<uint64_t, 16> CaseCounts;
- uint64_t MaxCount = 0;
- unsigned Version = 0;
- // Default case is in the front -- save the slot here.
- CaseCounts.push_back(0);
- for (auto &VD : VDs) {
- int64_t V = VD.Value;
- uint64_t C = VD.Count;
- if (MemOPScaleCount)
- C = getScaledCount(C, ActualCount, SavedTotalCount);
-
- // Only care precise value here.
- if (getMemOPSizeKind(V) != PreciseValue)
- continue;
-
- // ValueCounts are sorted on the count. Break at the first un-profitable
- // value.
- if (!isProfitable(C, RemainCount))
- break;
-
- SizeIds.push_back(V);
- CaseCounts.push_back(C);
- if (C > MaxCount)
- MaxCount = C;
-
- assert(RemainCount >= C);
- RemainCount -= C;
-
- if (++Version > MemOPMaxVersion && MemOPMaxVersion != 0)
- break;
- }
-
- if (Version == 0)
- return false;
-
- CaseCounts[0] = RemainCount;
- if (RemainCount > MaxCount)
- MaxCount = RemainCount;
-
- uint64_t SumForOpt = TotalCount - RemainCount;
-
- DEBUG(dbgs() << "Optimize one memory intrinsic call to " << Version
- << " Versions (covering " << SumForOpt << " out of "
- << TotalCount << ")\n");
-
- // mem_op(..., size)
- // ==>
- // switch (size) {
- // case s1:
- // mem_op(..., s1);
- // goto merge_bb;
- // case s2:
- // mem_op(..., s2);
- // goto merge_bb;
- // ...
- // default:
- // mem_op(..., size);
- // goto merge_bb;
- // }
- // merge_bb:
-
- BasicBlock *BB = MI->getParent();
- DEBUG(dbgs() << "\n\n== Basic Block Before ==\n");
- DEBUG(dbgs() << *BB << "\n");
- auto OrigBBFreq = BFI.getBlockFreq(BB);
-
- BasicBlock *DefaultBB = SplitBlock(BB, MI);
- BasicBlock::iterator It(*MI);
- ++It;
- assert(It != DefaultBB->end());
- BasicBlock *MergeBB = SplitBlock(DefaultBB, &(*It));
- MergeBB->setName("MemOP.Merge");
- BFI.setBlockFreq(MergeBB, OrigBBFreq.getFrequency());
- DefaultBB->setName("MemOP.Default");
-
- auto &Ctx = Func.getContext();
- IRBuilder<> IRB(BB);
- BB->getTerminator()->eraseFromParent();
- Value *SizeVar = MI->getLength();
- SwitchInst *SI = IRB.CreateSwitch(SizeVar, DefaultBB, SizeIds.size());
-
- // Clear the value profile data.
- MI->setMetadata(LLVMContext::MD_prof, nullptr);
-
- DEBUG(dbgs() << "\n\n== Basic Block After==\n");
-
- for (uint64_t SizeId : SizeIds) {
- ConstantInt *CaseSizeId = ConstantInt::get(Type::getInt64Ty(Ctx), SizeId);
- BasicBlock *CaseBB = BasicBlock::Create(
- Ctx, Twine("MemOP.Case.") + Twine(SizeId), &Func, DefaultBB);
- Instruction *NewInst = MI->clone();
- // Fix the argument.
- dyn_cast<MemIntrinsic>(NewInst)->setLength(CaseSizeId);
- CaseBB->getInstList().push_back(NewInst);
- IRBuilder<> IRBCase(CaseBB);
- IRBCase.CreateBr(MergeBB);
- SI->addCase(CaseSizeId, CaseBB);
- DEBUG(dbgs() << *CaseBB << "\n");
- }
- setProfMetadata(Func.getParent(), SI, CaseCounts, MaxCount);
-
- DEBUG(dbgs() << *BB << "\n");
- DEBUG(dbgs() << *DefaultBB << "\n");
- DEBUG(dbgs() << *MergeBB << "\n");
-
- emitOptimizationRemark(Func.getContext(), "memop-opt", Func,
- MI->getDebugLoc(),
- Twine("optimize ") + getMIName(MI) + " with count " +
- Twine(SumForOpt) + " out of " + Twine(TotalCount) +
- " for " + Twine(Version) + " versions");
-
- return true;
-}
-} // namespace
-
-static bool PGOMemOPSizeOptImpl(Function &F, BlockFrequencyInfo &BFI) {
- if (DisableMemOPOPT)
- return false;
-
- if (F.hasFnAttribute(Attribute::OptimizeForSize))
- return false;
- MemOPSizeOpt MemOPSizeOpt(F, BFI);
- MemOPSizeOpt.perform();
- return MemOPSizeOpt.isChanged();
-}
-
-bool PGOMemOPSizeOptLegacyPass::runOnFunction(Function &F) {
- BlockFrequencyInfo &BFI =
- getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
- return PGOMemOPSizeOptImpl(F, BFI);
-}
-
-namespace llvm {
-char &PGOMemOPSizeOptID = PGOMemOPSizeOptLegacyPass::ID;
-
-PreservedAnalyses PGOMemOPSizeOpt::run(Function &F,
- FunctionAnalysisManager &FAM) {
- auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
- bool Changed = PGOMemOPSizeOptImpl(F, BFI);
- if (!Changed)
- return PreservedAnalyses::all();
- auto PA = PreservedAnalyses();
- PA.preserve<GlobalsAA>();
- return PA;
-}
-} // namespace llvm
diff --git a/lib/Transforms/Instrumentation/InstrProfiling.cpp b/lib/Transforms/Instrumentation/InstrProfiling.cpp
index f83c930ca61b..37f88d5f95f1 100644
--- a/lib/Transforms/Instrumentation/InstrProfiling.cpp
+++ b/lib/Transforms/Instrumentation/InstrProfiling.cpp
@@ -343,14 +343,24 @@ static std::string getVarName(InstrProfIncrementInst *Inc, StringRef Prefix) {
static inline bool shouldRecordFunctionAddr(Function *F) {
// Check the linkage
+ bool HasAvailableExternallyLinkage = F->hasAvailableExternallyLinkage();
if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() &&
- !F->hasAvailableExternallyLinkage())
+ !HasAvailableExternallyLinkage)
return true;
+
+ // A function marked 'alwaysinline' with available_externally linkage can't
+ // have its address taken. Doing so would create an undefined external ref to
+ // the function, which would fail to link.
+ if (HasAvailableExternallyLinkage &&
+ F->hasFnAttribute(Attribute::AlwaysInline))
+ return false;
+
// Prohibit function address recording if the function is both internal and
// COMDAT. This avoids the profile data variable referencing internal symbols
// in COMDAT.
if (F->hasLocalLinkage() && F->hasComdat())
return false;
+
// Check uses of this function for other than direct calls or invokes to it.
// Inline virtual functions have linkeOnceODR linkage. When a key method
// exists, the vtable will only be emitted in the TU where the key method
diff --git a/lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp b/lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp
new file mode 100644
index 000000000000..0bc9ddfbe4d3
--- /dev/null
+++ b/lib/Transforms/Instrumentation/PGOMemOPSizeOpt.cpp
@@ -0,0 +1,419 @@
+//===-- PGOMemOPSizeOpt.cpp - Optimizations based on value profiling ===//
+//
+// 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 transformation that optimizes memory intrinsics
+// such as memcpy using the size value profile. When memory intrinsic size
+// value profile metadata is available, a single memory intrinsic is expanded
+// to a sequence of guarded specialized versions that are called with the
+// hottest size(s), for later expansion into more optimal inline sequences.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/BlockFrequencyInfo.h"
+#include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/PassSupport.h"
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Transforms/Instrumentation.h"
+#include "llvm/Transforms/PGOInstrumentation.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "pgo-memop-opt"
+
+STATISTIC(NumOfPGOMemOPOpt, "Number of memop intrinsics optimized.");
+STATISTIC(NumOfPGOMemOPAnnotate, "Number of memop intrinsics annotated.");
+
+// The minimum call count to optimize memory intrinsic calls.
+static cl::opt<unsigned>
+ MemOPCountThreshold("pgo-memop-count-threshold", cl::Hidden, cl::ZeroOrMore,
+ cl::init(1000),
+ cl::desc("The minimum count to optimize memory "
+ "intrinsic calls"));
+
+// Command line option to disable memory intrinsic optimization. The default is
+// false. This is for debug purpose.
+static cl::opt<bool> DisableMemOPOPT("disable-memop-opt", cl::init(false),
+ cl::Hidden, cl::desc("Disable optimize"));
+
+// The percent threshold to optimize memory intrinsic calls.
+static cl::opt<unsigned>
+ MemOPPercentThreshold("pgo-memop-percent-threshold", cl::init(40),
+ cl::Hidden, cl::ZeroOrMore,
+ cl::desc("The percentage threshold for the "
+ "memory intrinsic calls optimization"));
+
+// Maximum number of versions for optimizing memory intrinsic call.
+static cl::opt<unsigned>
+ MemOPMaxVersion("pgo-memop-max-version", cl::init(3), cl::Hidden,
+ cl::ZeroOrMore,
+ cl::desc("The max version for the optimized memory "
+ " intrinsic calls"));
+
+// Scale the counts from the annotation using the BB count value.
+static cl::opt<bool>
+ MemOPScaleCount("pgo-memop-scale-count", cl::init(true), cl::Hidden,
+ cl::desc("Scale the memop size counts using the basic "
+ " block count value"));
+
+// This option sets the rangge of precise profile memop sizes.
+extern cl::opt<std::string> MemOPSizeRange;
+
+// This option sets the value that groups large memop sizes
+extern cl::opt<unsigned> MemOPSizeLarge;
+
+namespace {
+class PGOMemOPSizeOptLegacyPass : public FunctionPass {
+public:
+ static char ID;
+
+ PGOMemOPSizeOptLegacyPass() : FunctionPass(ID) {
+ initializePGOMemOPSizeOptLegacyPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ StringRef getPassName() const override { return "PGOMemOPSize"; }
+
+private:
+ bool runOnFunction(Function &F) override;
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<BlockFrequencyInfoWrapperPass>();
+ AU.addPreserved<GlobalsAAWrapperPass>();
+ }
+};
+} // end anonymous namespace
+
+char PGOMemOPSizeOptLegacyPass::ID = 0;
+INITIALIZE_PASS_BEGIN(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt",
+ "Optimize memory intrinsic using its size value profile",
+ false, false)
+INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
+INITIALIZE_PASS_END(PGOMemOPSizeOptLegacyPass, "pgo-memop-opt",
+ "Optimize memory intrinsic using its size value profile",
+ false, false)
+
+FunctionPass *llvm::createPGOMemOPSizeOptLegacyPass() {
+ return new PGOMemOPSizeOptLegacyPass();
+}
+
+namespace {
+class MemOPSizeOpt : public InstVisitor<MemOPSizeOpt> {
+public:
+ MemOPSizeOpt(Function &Func, BlockFrequencyInfo &BFI)
+ : Func(Func), BFI(BFI), Changed(false) {
+ ValueDataArray =
+ llvm::make_unique<InstrProfValueData[]>(MemOPMaxVersion + 2);
+ // Get the MemOPSize range information from option MemOPSizeRange,
+ getMemOPSizeRangeFromOption(MemOPSizeRange, PreciseRangeStart,
+ PreciseRangeLast);
+ }
+ bool isChanged() const { return Changed; }
+ void perform() {
+ WorkList.clear();
+ visit(Func);
+
+ for (auto &MI : WorkList) {
+ ++NumOfPGOMemOPAnnotate;
+ if (perform(MI)) {
+ Changed = true;
+ ++NumOfPGOMemOPOpt;
+ DEBUG(dbgs() << "MemOP call: " << MI->getCalledFunction()->getName()
+ << "is Transformed.\n");
+ }
+ }
+ }
+
+ void visitMemIntrinsic(MemIntrinsic &MI) {
+ Value *Length = MI.getLength();
+ // Not perform on constant length calls.
+ if (dyn_cast<ConstantInt>(Length))
+ return;
+ WorkList.push_back(&MI);
+ }
+
+private:
+ Function &Func;
+ BlockFrequencyInfo &BFI;
+ bool Changed;
+ std::vector<MemIntrinsic *> WorkList;
+ // Start of the previse range.
+ int64_t PreciseRangeStart;
+ // Last value of the previse range.
+ int64_t PreciseRangeLast;
+ // The space to read the profile annotation.
+ std::unique_ptr<InstrProfValueData[]> ValueDataArray;
+ bool perform(MemIntrinsic *MI);
+
+ // This kind shows which group the value falls in. For PreciseValue, we have
+ // the profile count for that value. LargeGroup groups the values that are in
+ // range [LargeValue, +inf). NonLargeGroup groups the rest of values.
+ enum MemOPSizeKind { PreciseValue, NonLargeGroup, LargeGroup };
+
+ MemOPSizeKind getMemOPSizeKind(int64_t Value) const {
+ if (Value == MemOPSizeLarge && MemOPSizeLarge != 0)
+ return LargeGroup;
+ if (Value == PreciseRangeLast + 1)
+ return NonLargeGroup;
+ return PreciseValue;
+ }
+};
+
+static const char *getMIName(const MemIntrinsic *MI) {
+ switch (MI->getIntrinsicID()) {
+ case Intrinsic::memcpy:
+ return "memcpy";
+ case Intrinsic::memmove:
+ return "memmove";
+ case Intrinsic::memset:
+ return "memset";
+ default:
+ return "unknown";
+ }
+}
+
+static bool isProfitable(uint64_t Count, uint64_t TotalCount) {
+ assert(Count <= TotalCount);
+ if (Count < MemOPCountThreshold)
+ return false;
+ if (Count < TotalCount * MemOPPercentThreshold / 100)
+ return false;
+ return true;
+}
+
+static inline uint64_t getScaledCount(uint64_t Count, uint64_t Num,
+ uint64_t Denom) {
+ if (!MemOPScaleCount)
+ return Count;
+ bool Overflowed;
+ uint64_t ScaleCount = SaturatingMultiply(Count, Num, &Overflowed);
+ return ScaleCount / Denom;
+}
+
+bool MemOPSizeOpt::perform(MemIntrinsic *MI) {
+ assert(MI);
+ if (MI->getIntrinsicID() == Intrinsic::memmove)
+ return false;
+
+ uint32_t NumVals, MaxNumPromotions = MemOPMaxVersion + 2;
+ uint64_t TotalCount;
+ if (!getValueProfDataFromInst(*MI, IPVK_MemOPSize, MaxNumPromotions,
+ ValueDataArray.get(), NumVals, TotalCount))
+ return false;
+
+ uint64_t ActualCount = TotalCount;
+ uint64_t SavedTotalCount = TotalCount;
+ if (MemOPScaleCount) {
+ auto BBEdgeCount = BFI.getBlockProfileCount(MI->getParent());
+ if (!BBEdgeCount)
+ return false;
+ ActualCount = *BBEdgeCount;
+ }
+
+ ArrayRef<InstrProfValueData> VDs(ValueDataArray.get(), NumVals);
+ DEBUG(dbgs() << "Read one memory intrinsic profile with count " << ActualCount
+ << "\n");
+ DEBUG(
+ for (auto &VD
+ : VDs) { dbgs() << " (" << VD.Value << "," << VD.Count << ")\n"; });
+
+ if (ActualCount < MemOPCountThreshold)
+ return false;
+ // Skip if the total value profiled count is 0, in which case we can't
+ // scale up the counts properly (and there is no profitable transformation).
+ if (TotalCount == 0)
+ return false;
+
+ TotalCount = ActualCount;
+ if (MemOPScaleCount)
+ DEBUG(dbgs() << "Scale counts: numerator = " << ActualCount
+ << " denominator = " << SavedTotalCount << "\n");
+
+ // Keeping track of the count of the default case:
+ uint64_t RemainCount = TotalCount;
+ uint64_t SavedRemainCount = SavedTotalCount;
+ SmallVector<uint64_t, 16> SizeIds;
+ SmallVector<uint64_t, 16> CaseCounts;
+ uint64_t MaxCount = 0;
+ unsigned Version = 0;
+ // Default case is in the front -- save the slot here.
+ CaseCounts.push_back(0);
+ for (auto &VD : VDs) {
+ int64_t V = VD.Value;
+ uint64_t C = VD.Count;
+ if (MemOPScaleCount)
+ C = getScaledCount(C, ActualCount, SavedTotalCount);
+
+ // Only care precise value here.
+ if (getMemOPSizeKind(V) != PreciseValue)
+ continue;
+
+ // ValueCounts are sorted on the count. Break at the first un-profitable
+ // value.
+ if (!isProfitable(C, RemainCount))
+ break;
+
+ SizeIds.push_back(V);
+ CaseCounts.push_back(C);
+ if (C > MaxCount)
+ MaxCount = C;
+
+ assert(RemainCount >= C);
+ RemainCount -= C;
+ assert(SavedRemainCount >= VD.Count);
+ SavedRemainCount -= VD.Count;
+
+ if (++Version > MemOPMaxVersion && MemOPMaxVersion != 0)
+ break;
+ }
+
+ if (Version == 0)
+ return false;
+
+ CaseCounts[0] = RemainCount;
+ if (RemainCount > MaxCount)
+ MaxCount = RemainCount;
+
+ uint64_t SumForOpt = TotalCount - RemainCount;
+
+ DEBUG(dbgs() << "Optimize one memory intrinsic call to " << Version
+ << " Versions (covering " << SumForOpt << " out of "
+ << TotalCount << ")\n");
+
+ // mem_op(..., size)
+ // ==>
+ // switch (size) {
+ // case s1:
+ // mem_op(..., s1);
+ // goto merge_bb;
+ // case s2:
+ // mem_op(..., s2);
+ // goto merge_bb;
+ // ...
+ // default:
+ // mem_op(..., size);
+ // goto merge_bb;
+ // }
+ // merge_bb:
+
+ BasicBlock *BB = MI->getParent();
+ DEBUG(dbgs() << "\n\n== Basic Block Before ==\n");
+ DEBUG(dbgs() << *BB << "\n");
+ auto OrigBBFreq = BFI.getBlockFreq(BB);
+
+ BasicBlock *DefaultBB = SplitBlock(BB, MI);
+ BasicBlock::iterator It(*MI);
+ ++It;
+ assert(It != DefaultBB->end());
+ BasicBlock *MergeBB = SplitBlock(DefaultBB, &(*It));
+ MergeBB->setName("MemOP.Merge");
+ BFI.setBlockFreq(MergeBB, OrigBBFreq.getFrequency());
+ DefaultBB->setName("MemOP.Default");
+
+ auto &Ctx = Func.getContext();
+ IRBuilder<> IRB(BB);
+ BB->getTerminator()->eraseFromParent();
+ Value *SizeVar = MI->getLength();
+ SwitchInst *SI = IRB.CreateSwitch(SizeVar, DefaultBB, SizeIds.size());
+
+ // Clear the value profile data.
+ MI->setMetadata(LLVMContext::MD_prof, nullptr);
+ // If all promoted, we don't need the MD.prof metadata.
+ if (SavedRemainCount > 0 || Version != NumVals)
+ // Otherwise we need update with the un-promoted records back.
+ annotateValueSite(*Func.getParent(), *MI, VDs.slice(Version),
+ SavedRemainCount, IPVK_MemOPSize, NumVals);
+
+ DEBUG(dbgs() << "\n\n== Basic Block After==\n");
+
+ for (uint64_t SizeId : SizeIds) {
+ ConstantInt *CaseSizeId = ConstantInt::get(Type::getInt64Ty(Ctx), SizeId);
+ BasicBlock *CaseBB = BasicBlock::Create(
+ Ctx, Twine("MemOP.Case.") + Twine(SizeId), &Func, DefaultBB);
+ Instruction *NewInst = MI->clone();
+ // Fix the argument.
+ dyn_cast<MemIntrinsic>(NewInst)->setLength(CaseSizeId);
+ CaseBB->getInstList().push_back(NewInst);
+ IRBuilder<> IRBCase(CaseBB);
+ IRBCase.CreateBr(MergeBB);
+ SI->addCase(CaseSizeId, CaseBB);
+ DEBUG(dbgs() << *CaseBB << "\n");
+ }
+ setProfMetadata(Func.getParent(), SI, CaseCounts, MaxCount);
+
+ DEBUG(dbgs() << *BB << "\n");
+ DEBUG(dbgs() << *DefaultBB << "\n");
+ DEBUG(dbgs() << *MergeBB << "\n");
+
+ emitOptimizationRemark(Func.getContext(), "memop-opt", Func,
+ MI->getDebugLoc(),
+ Twine("optimize ") + getMIName(MI) + " with count " +
+ Twine(SumForOpt) + " out of " + Twine(TotalCount) +
+ " for " + Twine(Version) + " versions");
+
+ return true;
+}
+} // namespace
+
+static bool PGOMemOPSizeOptImpl(Function &F, BlockFrequencyInfo &BFI) {
+ if (DisableMemOPOPT)
+ return false;
+
+ if (F.hasFnAttribute(Attribute::OptimizeForSize))
+ return false;
+ MemOPSizeOpt MemOPSizeOpt(F, BFI);
+ MemOPSizeOpt.perform();
+ return MemOPSizeOpt.isChanged();
+}
+
+bool PGOMemOPSizeOptLegacyPass::runOnFunction(Function &F) {
+ BlockFrequencyInfo &BFI =
+ getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
+ return PGOMemOPSizeOptImpl(F, BFI);
+}
+
+namespace llvm {
+char &PGOMemOPSizeOptID = PGOMemOPSizeOptLegacyPass::ID;
+
+PreservedAnalyses PGOMemOPSizeOpt::run(Function &F,
+ FunctionAnalysisManager &FAM) {
+ auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(F);
+ bool Changed = PGOMemOPSizeOptImpl(F, BFI);
+ if (!Changed)
+ return PreservedAnalyses::all();
+ auto PA = PreservedAnalyses();
+ PA.preserve<GlobalsAA>();
+ return PA;
+}
+} // namespace llvm
diff --git a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 8aa40d1759de..e3c36c98ab0d 100644
--- a/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -61,7 +61,7 @@ static const char *const SanCov8bitCountersInitName =
"__sanitizer_cov_8bit_counters_init";
static const char *const SanCovGuardsSectionName = "sancov_guards";
-static const char *const SanCovCountersSectionName = "sancov_counters";
+static const char *const SanCovCountersSectionName = "sancov_cntrs";
static cl::opt<int> ClCoverageLevel(
"sanitizer-coverage-level",
diff --git a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 7b625b9b136e..2a4c9526dfcd 100644
--- a/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -551,7 +551,7 @@ static bool runImpl(Function &F, LazyValueInfo *LVI, const SimplifyQuery &SQ) {
BBChanged = true;
}
}
- };
+ }
FnChanged |= BBChanged;
}
diff --git a/lib/Transforms/Scalar/EarlyCSE.cpp b/lib/Transforms/Scalar/EarlyCSE.cpp
index c4f450949e6d..0f92760a874b 100644
--- a/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -15,6 +15,7 @@
#include "llvm/Transforms/Scalar/EarlyCSE.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/ScopedHashTable.h"
+#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/GlobalsModRef.h"
@@ -506,7 +507,7 @@ private:
if (MemoryAccess *MA = MSSA->getMemoryAccess(Inst)) {
// Optimize MemoryPhi nodes that may become redundant by having all the
// same input values once MA is removed.
- SmallVector<MemoryPhi *, 4> PhisToCheck;
+ SmallSetVector<MemoryPhi *, 4> PhisToCheck;
SmallVector<MemoryAccess *, 8> WorkQueue;
WorkQueue.push_back(MA);
// Process MemoryPhi nodes in FIFO order using a ever-growing vector since
@@ -517,7 +518,7 @@ private:
for (auto *U : WI->users())
if (MemoryPhi *MP = dyn_cast<MemoryPhi>(U))
- PhisToCheck.push_back(MP);
+ PhisToCheck.insert(MP);
MSSAUpdater->removeMemoryAccess(WI);
diff --git a/lib/Transforms/Scalar/GVNSink.cpp b/lib/Transforms/Scalar/GVNSink.cpp
index 8634816e702f..5fd2dfc118b4 100644
--- a/lib/Transforms/Scalar/GVNSink.cpp
+++ b/lib/Transforms/Scalar/GVNSink.cpp
@@ -64,6 +64,17 @@ using namespace llvm;
STATISTIC(NumRemoved, "Number of instructions removed");
+namespace llvm {
+namespace GVNExpression {
+
+LLVM_DUMP_METHOD void Expression::dump() const {
+ print(dbgs());
+ dbgs() << "\n";
+}
+
+}
+}
+
namespace {
static bool isMemoryInst(const Instruction *I) {
diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index b706152f30c8..8b435050ac76 100644
--- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -983,21 +983,21 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
const SCEV *NumBytesS =
SE->getAddExpr(BECount, SE->getOne(IntPtrTy), SCEV::FlagNUW);
+ if (StoreSize != 1)
+ NumBytesS = SE->getMulExpr(NumBytesS, SE->getConstant(IntPtrTy, StoreSize),
+ SCEV::FlagNUW);
+
+ Value *NumBytes =
+ Expander.expandCodeFor(NumBytesS, IntPtrTy, Preheader->getTerminator());
+
unsigned Align = std::min(SI->getAlignment(), LI->getAlignment());
CallInst *NewCall = nullptr;
// Check whether to generate an unordered atomic memcpy:
// If the load or store are atomic, then they must neccessarily be unordered
// by previous checks.
- if (!SI->isAtomic() && !LI->isAtomic()) {
- if (StoreSize != 1)
- NumBytesS = SE->getMulExpr(
- NumBytesS, SE->getConstant(IntPtrTy, StoreSize), SCEV::FlagNUW);
-
- Value *NumBytes =
- Expander.expandCodeFor(NumBytesS, IntPtrTy, Preheader->getTerminator());
-
+ if (!SI->isAtomic() && !LI->isAtomic())
NewCall = Builder.CreateMemCpy(StoreBasePtr, LoadBasePtr, NumBytes, Align);
- } else {
+ else {
// We cannot allow unaligned ops for unordered load/store, so reject
// anything where the alignment isn't at least the element size.
if (Align < StoreSize)
@@ -1010,11 +1010,9 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
if (StoreSize > TTI->getAtomicMemIntrinsicMaxElementSize())
return false;
- Value *NumElements =
- Expander.expandCodeFor(NumBytesS, IntPtrTy, Preheader->getTerminator());
+ NewCall = Builder.CreateElementUnorderedAtomicMemCpy(
+ StoreBasePtr, LoadBasePtr, NumBytes, StoreSize);
- NewCall = Builder.CreateElementAtomicMemCpy(StoreBasePtr, LoadBasePtr,
- NumElements, StoreSize);
// Propagate alignment info onto the pointer args. Note that unordered
// atomic loads/stores are *required* by the spec to have an alignment
// but non-atomic loads/stores may not.
diff --git a/lib/Transforms/Scalar/NewGVN.cpp b/lib/Transforms/Scalar/NewGVN.cpp
index 6926aae37963..cbbd55512c9f 100644
--- a/lib/Transforms/Scalar/NewGVN.cpp
+++ b/lib/Transforms/Scalar/NewGVN.cpp
@@ -2195,7 +2195,7 @@ void NewGVN::moveValueToNewCongruenceClass(Instruction *I, const Expression *E,
// For a given expression, mark the phi of ops instructions that could have
// changed as a result.
void NewGVN::markPhiOfOpsChanged(const Expression *E) {
- touchAndErase(ExpressionToPhiOfOps, E);
+ touchAndErase(ExpressionToPhiOfOps, ExactEqualsExpression(*E));
}
// Perform congruence finding on a given value numbering expression.
@@ -3561,7 +3561,7 @@ bool NewGVN::eliminateInstructions(Function &F) {
// TODO: It would be faster to use getNumIncomingBlocks() on a phi node in
// the block and subtract the pred count, but it's more complicated.
if (ReachablePredCount.lookup(BB) !=
- std::distance(pred_begin(BB), pred_end(BB))) {
+ unsigned(std::distance(pred_begin(BB), pred_end(BB)))) {
for (auto II = BB->begin(); isa<PHINode>(II); ++II) {
auto &PHI = cast<PHINode>(*II);
ReplaceUnreachablePHIArgs(PHI, BB);
diff --git a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
index bae7911d222c..a52739bb76f7 100644
--- a/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
+++ b/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
@@ -89,10 +89,10 @@ struct RewriteStatepointsForGC : public ModulePass {
Changed |= runOnFunction(F);
if (Changed) {
- // stripNonValidAttributes asserts that shouldRewriteStatepointsIn
+ // stripNonValidAttributesAndMetadata asserts that shouldRewriteStatepointsIn
// returns true for at least one function in the module. Since at least
// one function changed, we know that the precondition is satisfied.
- stripNonValidAttributes(M);
+ stripNonValidAttributesAndMetadata(M);
}
return Changed;
@@ -105,20 +105,24 @@ struct RewriteStatepointsForGC : public ModulePass {
AU.addRequired<TargetTransformInfoWrapperPass>();
}
- /// The IR fed into RewriteStatepointsForGC may have had attributes implying
- /// dereferenceability that are no longer valid/correct after
- /// RewriteStatepointsForGC has run. This is because semantically, after
+ /// The IR fed into RewriteStatepointsForGC may have had attributes and
+ /// metadata implying dereferenceability that are no longer valid/correct after
+ /// RewriteStatepointsForGC has run. This is because semantically, after
/// RewriteStatepointsForGC runs, all calls to gc.statepoint "free" the entire
- /// heap. stripNonValidAttributes (conservatively) restores correctness
- /// by erasing all attributes in the module that externally imply
- /// dereferenceability.
- /// Similar reasoning also applies to the noalias attributes. gc.statepoint
- /// can touch the entire heap including noalias objects.
- void stripNonValidAttributes(Module &M);
-
- // Helpers for stripNonValidAttributes
- void stripNonValidAttributesFromBody(Function &F);
+ /// heap. stripNonValidAttributesAndMetadata (conservatively) restores
+ /// correctness by erasing all attributes in the module that externally imply
+ /// dereferenceability. Similar reasoning also applies to the noalias
+ /// attributes and metadata. gc.statepoint can touch the entire heap including
+ /// noalias objects.
+ void stripNonValidAttributesAndMetadata(Module &M);
+
+ // Helpers for stripNonValidAttributesAndMetadata
+ void stripNonValidAttributesAndMetadataFromBody(Function &F);
void stripNonValidAttributesFromPrototype(Function &F);
+ // Certain metadata on instructions are invalid after running RS4GC.
+ // Optimizations that run after RS4GC can incorrectly use this metadata to
+ // optimize functions. We drop such metadata on the instruction.
+ void stripInvalidMetadataFromInstruction(Instruction &I);
};
} // namespace
@@ -2306,13 +2310,44 @@ RewriteStatepointsForGC::stripNonValidAttributesFromPrototype(Function &F) {
RemoveNonValidAttrAtIndex(Ctx, F, AttributeList::ReturnIndex);
}
-void RewriteStatepointsForGC::stripNonValidAttributesFromBody(Function &F) {
+void RewriteStatepointsForGC::stripInvalidMetadataFromInstruction(Instruction &I) {
+
+ if (!isa<LoadInst>(I) && !isa<StoreInst>(I))
+ return;
+ // These are the attributes that are still valid on loads and stores after
+ // RS4GC.
+ // The metadata implying dereferenceability and noalias are (conservatively)
+ // dropped. This is because semantically, after RewriteStatepointsForGC runs,
+ // all calls to gc.statepoint "free" the entire heap. Also, gc.statepoint can
+ // touch the entire heap including noalias objects. Note: The reasoning is
+ // same as stripping the dereferenceability and noalias attributes that are
+ // analogous to the metadata counterparts.
+ // We also drop the invariant.load metadata on the load because that metadata
+ // implies the address operand to the load points to memory that is never
+ // changed once it became dereferenceable. This is no longer true after RS4GC.
+ // Similar reasoning applies to invariant.group metadata, which applies to
+ // loads within a group.
+ unsigned ValidMetadataAfterRS4GC[] = {LLVMContext::MD_tbaa,
+ LLVMContext::MD_range,
+ LLVMContext::MD_alias_scope,
+ LLVMContext::MD_nontemporal,
+ LLVMContext::MD_nonnull,
+ LLVMContext::MD_align,
+ LLVMContext::MD_type};
+
+ // Drops all metadata on the instruction other than ValidMetadataAfterRS4GC.
+ I.dropUnknownNonDebugMetadata(ValidMetadataAfterRS4GC);
+
+}
+
+void RewriteStatepointsForGC::stripNonValidAttributesAndMetadataFromBody(Function &F) {
if (F.empty())
return;
LLVMContext &Ctx = F.getContext();
MDBuilder Builder(Ctx);
+
for (Instruction &I : instructions(F)) {
if (const MDNode *MD = I.getMetadata(LLVMContext::MD_tbaa)) {
assert(MD->getNumOperands() < 5 && "unrecognized metadata shape!");
@@ -2333,6 +2368,8 @@ void RewriteStatepointsForGC::stripNonValidAttributesFromBody(Function &F) {
I.setMetadata(LLVMContext::MD_tbaa, MutableTBAA);
}
+ stripInvalidMetadataFromInstruction(I);
+
if (CallSite CS = CallSite(&I)) {
for (int i = 0, e = CS.arg_size(); i != e; i++)
if (isa<PointerType>(CS.getArgument(i)->getType()))
@@ -2357,7 +2394,7 @@ static bool shouldRewriteStatepointsIn(Function &F) {
return false;
}
-void RewriteStatepointsForGC::stripNonValidAttributes(Module &M) {
+void RewriteStatepointsForGC::stripNonValidAttributesAndMetadata(Module &M) {
#ifndef NDEBUG
assert(any_of(M, shouldRewriteStatepointsIn) && "precondition!");
#endif
@@ -2366,7 +2403,7 @@ void RewriteStatepointsForGC::stripNonValidAttributes(Module &M) {
stripNonValidAttributesFromPrototype(F);
for (Function &F : M)
- stripNonValidAttributesFromBody(F);
+ stripNonValidAttributesAndMetadataFromBody(F);
}
bool RewriteStatepointsForGC::runOnFunction(Function &F) {
diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp
index 815492ac354c..c6929c33b3e9 100644
--- a/lib/Transforms/Scalar/SCCP.cpp
+++ b/lib/Transforms/Scalar/SCCP.cpp
@@ -515,10 +515,6 @@ private:
void visitCmpInst(CmpInst &I);
void visitExtractValueInst(ExtractValueInst &EVI);
void visitInsertValueInst(InsertValueInst &IVI);
- void visitLandingPadInst(LandingPadInst &I) { markOverdefined(&I); }
- void visitFuncletPadInst(FuncletPadInst &FPI) {
- markOverdefined(&FPI);
- }
void visitCatchSwitchInst(CatchSwitchInst &CPI) {
markOverdefined(&CPI);
visitTerminatorInst(CPI);
@@ -539,13 +535,6 @@ private:
void visitResumeInst (TerminatorInst &I) { /*returns void*/ }
void visitUnreachableInst(TerminatorInst &I) { /*returns void*/ }
void visitFenceInst (FenceInst &I) { /*returns void*/ }
- void visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
- markOverdefined(&I);
- }
- void visitAtomicRMWInst (AtomicRMWInst &I) { markOverdefined(&I); }
- void visitAllocaInst (Instruction &I) { markOverdefined(&I); }
- void visitVAArgInst (Instruction &I) { markOverdefined(&I); }
-
void visitInstruction(Instruction &I) {
// If a new instruction is added to LLVM that we don't handle.
DEBUG(dbgs() << "SCCP: Don't know how to handle: " << I << '\n');
diff --git a/lib/Transforms/Utils/CodeExtractor.cpp b/lib/Transforms/Utils/CodeExtractor.cpp
index 24d28a6c2831..5d57ed9718fb 100644
--- a/lib/Transforms/Utils/CodeExtractor.cpp
+++ b/lib/Transforms/Utils/CodeExtractor.cpp
@@ -142,8 +142,139 @@ static bool definedInCaller(const SetVector<BasicBlock *> &Blocks, Value *V) {
return false;
}
-void CodeExtractor::findAllocas(ValueSet &SinkCands) const {
+static BasicBlock *getCommonExitBlock(const SetVector<BasicBlock *> &Blocks) {
+ BasicBlock *CommonExitBlock = nullptr;
+ auto hasNonCommonExitSucc = [&](BasicBlock *Block) {
+ for (auto *Succ : successors(Block)) {
+ // Internal edges, ok.
+ if (Blocks.count(Succ))
+ continue;
+ if (!CommonExitBlock) {
+ CommonExitBlock = Succ;
+ continue;
+ }
+ if (CommonExitBlock == Succ)
+ continue;
+
+ return true;
+ }
+ return false;
+ };
+
+ if (any_of(Blocks, hasNonCommonExitSucc))
+ return nullptr;
+
+ return CommonExitBlock;
+}
+
+bool CodeExtractor::isLegalToShrinkwrapLifetimeMarkers(
+ Instruction *Addr) const {
+ AllocaInst *AI = cast<AllocaInst>(Addr->stripInBoundsConstantOffsets());
+ Function *Func = (*Blocks.begin())->getParent();
+ for (BasicBlock &BB : *Func) {
+ if (Blocks.count(&BB))
+ continue;
+ for (Instruction &II : BB) {
+
+ if (isa<DbgInfoIntrinsic>(II))
+ continue;
+
+ unsigned Opcode = II.getOpcode();
+ Value *MemAddr = nullptr;
+ switch (Opcode) {
+ case Instruction::Store:
+ case Instruction::Load: {
+ if (Opcode == Instruction::Store) {
+ StoreInst *SI = cast<StoreInst>(&II);
+ MemAddr = SI->getPointerOperand();
+ } else {
+ LoadInst *LI = cast<LoadInst>(&II);
+ MemAddr = LI->getPointerOperand();
+ }
+ // Global variable can not be aliased with locals.
+ if (dyn_cast<Constant>(MemAddr))
+ break;
+ Value *Base = MemAddr->stripInBoundsConstantOffsets();
+ if (!dyn_cast<AllocaInst>(Base) || Base == AI)
+ return false;
+ break;
+ }
+ default: {
+ IntrinsicInst *IntrInst = dyn_cast<IntrinsicInst>(&II);
+ if (IntrInst) {
+ if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start ||
+ IntrInst->getIntrinsicID() == Intrinsic::lifetime_end)
+ break;
+ return false;
+ }
+ // Treat all the other cases conservatively if it has side effects.
+ if (II.mayHaveSideEffects())
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+BasicBlock *
+CodeExtractor::findOrCreateBlockForHoisting(BasicBlock *CommonExitBlock) {
+ BasicBlock *SinglePredFromOutlineRegion = nullptr;
+ assert(!Blocks.count(CommonExitBlock) &&
+ "Expect a block outside the region!");
+ for (auto *Pred : predecessors(CommonExitBlock)) {
+ if (!Blocks.count(Pred))
+ continue;
+ if (!SinglePredFromOutlineRegion) {
+ SinglePredFromOutlineRegion = Pred;
+ } else if (SinglePredFromOutlineRegion != Pred) {
+ SinglePredFromOutlineRegion = nullptr;
+ break;
+ }
+ }
+
+ if (SinglePredFromOutlineRegion)
+ return SinglePredFromOutlineRegion;
+
+#ifndef NDEBUG
+ auto getFirstPHI = [](BasicBlock *BB) {
+ BasicBlock::iterator I = BB->begin();
+ PHINode *FirstPhi = nullptr;
+ while (I != BB->end()) {
+ PHINode *Phi = dyn_cast<PHINode>(I);
+ if (!Phi)
+ break;
+ if (!FirstPhi) {
+ FirstPhi = Phi;
+ break;
+ }
+ }
+ return FirstPhi;
+ };
+ // If there are any phi nodes, the single pred either exists or has already
+ // be created before code extraction.
+ assert(!getFirstPHI(CommonExitBlock) && "Phi not expected");
+#endif
+
+ BasicBlock *NewExitBlock = CommonExitBlock->splitBasicBlock(
+ CommonExitBlock->getFirstNonPHI()->getIterator());
+
+ for (auto *Pred : predecessors(CommonExitBlock)) {
+ if (Blocks.count(Pred))
+ continue;
+ Pred->getTerminator()->replaceUsesOfWith(CommonExitBlock, NewExitBlock);
+ }
+ // Now add the old exit block to the outline region.
+ Blocks.insert(CommonExitBlock);
+ return CommonExitBlock;
+}
+
+void CodeExtractor::findAllocas(ValueSet &SinkCands, ValueSet &HoistCands,
+ BasicBlock *&ExitBlock) const {
Function *Func = (*Blocks.begin())->getParent();
+ ExitBlock = getCommonExitBlock(Blocks);
+
for (BasicBlock &BB : *Func) {
if (Blocks.count(&BB))
continue;
@@ -152,49 +283,96 @@ void CodeExtractor::findAllocas(ValueSet &SinkCands) const {
if (!AI)
continue;
- // Returns true if matching life time markers are found within
- // the outlined region.
- auto GetLifeTimeMarkers = [&](Instruction *Addr) {
+ // Find the pair of life time markers for address 'Addr' that are either
+ // defined inside the outline region or can legally be shrinkwrapped into
+ // the outline region. If there are not other untracked uses of the
+ // address, return the pair of markers if found; otherwise return a pair
+ // of nullptr.
+ auto GetLifeTimeMarkers =
+ [&](Instruction *Addr, bool &SinkLifeStart,
+ bool &HoistLifeEnd) -> std::pair<Instruction *, Instruction *> {
Instruction *LifeStart = nullptr, *LifeEnd = nullptr;
- for (User *U : Addr->users()) {
- if (!definedInRegion(Blocks, U))
- return false;
+ for (User *U : Addr->users()) {
IntrinsicInst *IntrInst = dyn_cast<IntrinsicInst>(U);
if (IntrInst) {
- if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start)
+ if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_start) {
+ // Do not handle the case where AI has multiple start markers.
+ if (LifeStart)
+ return std::make_pair<Instruction *>(nullptr, nullptr);
LifeStart = IntrInst;
- if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end)
+ }
+ if (IntrInst->getIntrinsicID() == Intrinsic::lifetime_end) {
+ if (LifeEnd)
+ return std::make_pair<Instruction *>(nullptr, nullptr);
LifeEnd = IntrInst;
+ }
+ continue;
}
+ // Find untracked uses of the address, bail.
+ if (!definedInRegion(Blocks, U))
+ return std::make_pair<Instruction *>(nullptr, nullptr);
}
- return LifeStart && LifeEnd;
+
+ if (!LifeStart || !LifeEnd)
+ return std::make_pair<Instruction *>(nullptr, nullptr);
+
+ SinkLifeStart = !definedInRegion(Blocks, LifeStart);
+ HoistLifeEnd = !definedInRegion(Blocks, LifeEnd);
+ // Do legality Check.
+ if ((SinkLifeStart || HoistLifeEnd) &&
+ !isLegalToShrinkwrapLifetimeMarkers(Addr))
+ return std::make_pair<Instruction *>(nullptr, nullptr);
+
+ // Check to see if we have a place to do hoisting, if not, bail.
+ if (HoistLifeEnd && !ExitBlock)
+ return std::make_pair<Instruction *>(nullptr, nullptr);
+
+ return std::make_pair(LifeStart, LifeEnd);
};
- if (GetLifeTimeMarkers(AI)) {
+ bool SinkLifeStart = false, HoistLifeEnd = false;
+ auto Markers = GetLifeTimeMarkers(AI, SinkLifeStart, HoistLifeEnd);
+
+ if (Markers.first) {
+ if (SinkLifeStart)
+ SinkCands.insert(Markers.first);
SinkCands.insert(AI);
+ if (HoistLifeEnd)
+ HoistCands.insert(Markers.second);
continue;
}
- // Follow the bitcast:
+ // Follow the bitcast.
Instruction *MarkerAddr = nullptr;
for (User *U : AI->users()) {
- if (U->stripPointerCasts() == AI) {
+
+ if (U->stripInBoundsConstantOffsets() == AI) {
+ SinkLifeStart = false;
+ HoistLifeEnd = false;
Instruction *Bitcast = cast<Instruction>(U);
- if (GetLifeTimeMarkers(Bitcast)) {
+ Markers = GetLifeTimeMarkers(Bitcast, SinkLifeStart, HoistLifeEnd);
+ if (Markers.first) {
MarkerAddr = Bitcast;
continue;
}
}
+
+ // Found unknown use of AI.
if (!definedInRegion(Blocks, U)) {
MarkerAddr = nullptr;
break;
}
}
+
if (MarkerAddr) {
+ if (SinkLifeStart)
+ SinkCands.insert(Markers.first);
if (!definedInRegion(Blocks, MarkerAddr))
SinkCands.insert(MarkerAddr);
SinkCands.insert(AI);
+ if (HoistLifeEnd)
+ HoistCands.insert(Markers.second);
}
}
}
@@ -780,7 +958,8 @@ Function *CodeExtractor::extractCodeRegion() {
if (!isEligible())
return nullptr;
- ValueSet inputs, outputs, SinkingCands;
+ ValueSet inputs, outputs, SinkingCands, HoistingCands;
+ BasicBlock *CommonExit = nullptr;
// Assumption: this is a single-entry code region, and the header is the first
// block in the region.
@@ -819,7 +998,8 @@ Function *CodeExtractor::extractCodeRegion() {
"newFuncRoot");
newFuncRoot->getInstList().push_back(BranchInst::Create(header));
- findAllocas(SinkingCands);
+ findAllocas(SinkingCands, HoistingCands, CommonExit);
+ assert(HoistingCands.empty() || CommonExit);
// Find inputs to, outputs from the code region.
findInputsOutputs(inputs, outputs, SinkingCands);
@@ -829,6 +1009,13 @@ Function *CodeExtractor::extractCodeRegion() {
cast<Instruction>(II)->moveBefore(*newFuncRoot,
newFuncRoot->getFirstInsertionPt());
+ if (!HoistingCands.empty()) {
+ auto *HoistToBlock = findOrCreateBlockForHoisting(CommonExit);
+ Instruction *TI = HoistToBlock->getTerminator();
+ for (auto *II : HoistingCands)
+ cast<Instruction>(II)->moveBefore(TI);
+ }
+
// Calculate the exit blocks for the extracted region and the total exit
// weights for each of those blocks.
DenseMap<BasicBlock *, BlockFrequency> ExitWeights;
diff --git a/lib/Transforms/Utils/PredicateInfo.cpp b/lib/Transforms/Utils/PredicateInfo.cpp
index 9e71cba4f1b7..1260e35e934d 100644
--- a/lib/Transforms/Utils/PredicateInfo.cpp
+++ b/lib/Transforms/Utils/PredicateInfo.cpp
@@ -460,6 +460,9 @@ void PredicateInfo::buildPredicateInfo() {
if (auto *BI = dyn_cast<BranchInst>(BranchBB->getTerminator())) {
if (!BI->isConditional())
continue;
+ // Can't insert conditional information if they all go to the same place.
+ if (BI->getSuccessor(0) == BI->getSuccessor(1))
+ continue;
processBranch(BI, BranchBB, OpsToRename);
} else if (auto *SI = dyn_cast<SwitchInst>(BranchBB->getTerminator())) {
processSwitch(SI, BranchBB, OpsToRename);
diff --git a/lib/Transforms/Utils/SimplifyIndVar.cpp b/lib/Transforms/Utils/SimplifyIndVar.cpp
index 02a5d3dbeadf..faa14046b1e3 100644
--- a/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -352,7 +352,7 @@ bool SimplifyIndvar::eliminateOverflowIntrinsic(CallInst *CI) {
return false;
typedef const SCEV *(ScalarEvolution::*OperationFunctionTy)(
- const SCEV *, const SCEV *, SCEV::NoWrapFlags);
+ const SCEV *, const SCEV *, SCEV::NoWrapFlags, unsigned);
typedef const SCEV *(ScalarEvolution::*ExtensionFunctionTy)(
const SCEV *, Type *);
@@ -406,10 +406,11 @@ bool SimplifyIndvar::eliminateOverflowIntrinsic(CallInst *CI) {
IntegerType::get(NarrowTy->getContext(), NarrowTy->getBitWidth() * 2);
const SCEV *A =
- (SE->*Extension)((SE->*Operation)(LHS, RHS, SCEV::FlagAnyWrap), WideTy);
+ (SE->*Extension)((SE->*Operation)(LHS, RHS, SCEV::FlagAnyWrap, 0u),
+ WideTy);
const SCEV *B =
(SE->*Operation)((SE->*Extension)(LHS, WideTy),
- (SE->*Extension)(RHS, WideTy), SCEV::FlagAnyWrap);
+ (SE->*Extension)(RHS, WideTy), SCEV::FlagAnyWrap, 0u);
if (A != B)
return false;
@@ -530,8 +531,7 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
return false;
const SCEV *(ScalarEvolution::*GetExprForBO)(const SCEV *, const SCEV *,
- SCEV::NoWrapFlags);
-
+ SCEV::NoWrapFlags, unsigned);
switch (BO->getOpcode()) {
default:
return false;
@@ -560,7 +560,7 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
const SCEV *ExtendAfterOp = SE->getZeroExtendExpr(SE->getSCEV(BO), WideTy);
const SCEV *OpAfterExtend = (SE->*GetExprForBO)(
SE->getZeroExtendExpr(LHS, WideTy), SE->getZeroExtendExpr(RHS, WideTy),
- SCEV::FlagAnyWrap);
+ SCEV::FlagAnyWrap, 0u);
if (ExtendAfterOp == OpAfterExtend) {
BO->setHasNoUnsignedWrap();
SE->forgetValue(BO);
@@ -572,7 +572,7 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
const SCEV *ExtendAfterOp = SE->getSignExtendExpr(SE->getSCEV(BO), WideTy);
const SCEV *OpAfterExtend = (SE->*GetExprForBO)(
SE->getSignExtendExpr(LHS, WideTy), SE->getSignExtendExpr(RHS, WideTy),
- SCEV::FlagAnyWrap);
+ SCEV::FlagAnyWrap, 0u);
if (ExtendAfterOp == OpAfterExtend) {
BO->setHasNoSignedWrap();
SE->forgetValue(BO);
diff --git a/test/Analysis/ScalarEvolution/limit-depth.ll b/test/Analysis/ScalarEvolution/limit-depth.ll
new file mode 100644
index 000000000000..5a35bfefd20a
--- /dev/null
+++ b/test/Analysis/ScalarEvolution/limit-depth.ll
@@ -0,0 +1,44 @@
+; RUN: opt -scalar-evolution-max-arith-depth=0 -analyze -scalar-evolution < %s | FileCheck %s
+
+; Check that depth set to 0 prevents getAddExpr and getMulExpr from making
+; transformations in SCEV. We expect the result to be very straightforward.
+
+define void @test_add(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
+; CHECK-LABEL: @test_add
+; CHECK: %s2 = add i32 %s1, %p3
+; CHECK-NEXT: --> (%a + %a + %b + %b + %c + %c + %d + %d + %e + %e + %f + %f)
+ %tmp0 = add i32 %a, %b
+ %tmp1 = add i32 %b, %c
+ %tmp2 = add i32 %c, %d
+ %tmp3 = add i32 %d, %e
+ %tmp4 = add i32 %e, %f
+ %tmp5 = add i32 %f, %a
+
+ %p1 = add i32 %tmp0, %tmp3
+ %p2 = add i32 %tmp1, %tmp4
+ %p3 = add i32 %tmp2, %tmp5
+
+ %s1 = add i32 %p1, %p2
+ %s2 = add i32 %s1, %p3
+ ret void
+}
+
+define void @test_mul(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) {
+; CHECK-LABEL: @test_mul
+; CHECK: %s2 = mul i32 %s1, %p3
+; CHECK-NEXT: --> (2 * 3 * 4 * 5 * 6 * 7 * %a * %b * %c * %d * %e * %f)
+ %tmp0 = mul i32 %a, 2
+ %tmp1 = mul i32 %b, 3
+ %tmp2 = mul i32 %c, 4
+ %tmp3 = mul i32 %d, 5
+ %tmp4 = mul i32 %e, 6
+ %tmp5 = mul i32 %f, 7
+
+ %p1 = mul i32 %tmp0, %tmp3
+ %p2 = mul i32 %tmp1, %tmp4
+ %p3 = mul i32 %tmp2, %tmp5
+
+ %s1 = mul i32 %p1, %p2
+ %s2 = mul i32 %s1, %p3
+ ret void
+}
diff --git a/test/Assembler/diexpression.ll b/test/Assembler/diexpression.ll
index c2fa3ee14c23..39f4be70145a 100644
--- a/test/Assembler/diexpression.ll
+++ b/test/Assembler/diexpression.ll
@@ -1,18 +1,20 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s
-; CHECK: !named = !{!0, !1, !2, !3, !4, !5}
-!named = !{!0, !1, !2, !3, !4, !5}
+; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6}
+!named = !{!0, !1, !2, !3, !4, !5, !6}
; CHECK: !0 = !DIExpression()
; CHECK-NEXT: !1 = !DIExpression(DW_OP_deref)
-; CHECK-NEXT: !2 = !DIExpression(DW_OP_plus, 3)
+; CHECK-NEXT: !2 = !DIExpression(DW_OP_constu, 3, DW_OP_plus)
; CHECK-NEXT: !3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
-; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
+; CHECK-NEXT: !4 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7)
; CHECK-NEXT: !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
+; CHECK-NEXT: !6 = !DIExpression(DW_OP_plus_uconst, 3)
!0 = !DIExpression()
!1 = !DIExpression(DW_OP_deref)
-!2 = !DIExpression(DW_OP_plus, 3)
+!2 = !DIExpression(DW_OP_constu, 3, DW_OP_plus)
!3 = !DIExpression(DW_OP_LLVM_fragment, 3, 7)
-!4 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_LLVM_fragment, 3, 7)
+!4 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7)
!5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
+!6 = !DIExpression(DW_OP_plus_uconst, 3)
diff --git a/test/Bitcode/DIExpression-deref.ll b/test/Bitcode/DIExpression-deref.ll
index 3a161b8ee4d2..a03d6016523e 100644
--- a/test/Bitcode/DIExpression-deref.ll
+++ b/test/Bitcode/DIExpression-deref.ll
@@ -11,11 +11,11 @@
!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
; DW_OP_deref should be moved to the back of the expression.
;
-; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref, DW_OP_LLVM_fragment, 8, 32)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 0, DW_OP_deref, DW_OP_LLVM_fragment, 8, 32)
!6 = !DIExpression(DW_OP_deref, DW_OP_plus, 0, DW_OP_LLVM_fragment, 8, 32)
-; CHECK: !DIExpression(DW_OP_plus, 0, DW_OP_deref)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 0, DW_OP_deref)
!7 = !DIExpression(DW_OP_deref, DW_OP_plus, 0)
-; CHECK: !DIExpression(DW_OP_plus, 1, DW_OP_deref)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 1, DW_OP_deref)
!8 = !DIExpression(DW_OP_plus, 1, DW_OP_deref)
; CHECK: !DIExpression(DW_OP_deref)
!9 = !DIExpression(DW_OP_deref)
diff --git a/test/Bitcode/DIExpression-minus-upgrade.ll b/test/Bitcode/DIExpression-minus-upgrade.ll
new file mode 100644
index 000000000000..1f26eba6f98c
--- /dev/null
+++ b/test/Bitcode/DIExpression-minus-upgrade.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-dis -o - %s.bc | FileCheck %s
+
+!llvm.dbg.cu = !{!1}
+!llvm.module.flags = !{!8, !9}
+
+!0 = distinct !DIGlobalVariable(name: "g", scope: !1, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true)
+!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang (llvm/trunk 304286)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3, globals: !4)
+!2 = !DIFile(filename: "a.c", directory: "/")
+!3 = !{}
+!4 = !{!7}
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK: !DIExpression(DW_OP_constu, 42, DW_OP_minus)
+!6 = !DIExpression(DW_OP_minus, 42)
+!7 = !DIGlobalVariableExpression(var: !0, expr: !6)
+!8 = !{i32 2, !"Dwarf Version", i32 4}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
diff --git a/test/Bitcode/DIExpression-minus-upgrade.ll.bc b/test/Bitcode/DIExpression-minus-upgrade.ll.bc
new file mode 100644
index 000000000000..354ba6454c3f
--- /dev/null
+++ b/test/Bitcode/DIExpression-minus-upgrade.ll.bc
Binary files differ
diff --git a/test/Bitcode/DIGlobalVariableExpression.ll b/test/Bitcode/DIGlobalVariableExpression.ll
index f6796bbdb7a0..31c3fda1b00a 100644
--- a/test/Bitcode/DIGlobalVariableExpression.ll
+++ b/test/Bitcode/DIGlobalVariableExpression.ll
@@ -14,7 +14,7 @@
; CHECK: ![[HVAR:[0-9]+]] = distinct !DIGlobalVariable(name: "h",
; CHECK: ![[IMPORTS]] = !{![[CIMPORT:[0-9]+]]}
; CHECK: ![[CIMPORT]] = !DIImportedEntity({{.*}}entity: ![[HVAR]]
-; CHECK: ![[GEXPR]] = !DIExpression(DW_OP_plus, 1)
+; CHECK: ![[GEXPR]] = !DIExpression(DW_OP_plus_uconst, 1)
; CHECK: ![[H]] = {{.*}}!DIGlobalVariableExpression(var: ![[HVAR]])
@g = common global i32 0, align 4, !dbg !0
diff --git a/test/Bitcode/upgrade-linker-options.ll b/test/Bitcode/upgrade-linker-options.ll
new file mode 100644
index 000000000000..6c874fa81e64
--- /dev/null
+++ b/test/Bitcode/upgrade-linker-options.ll
@@ -0,0 +1,15 @@
+; RUN: llvm-as -disable-verify < %s | llvm-dis | FileCheck %s
+; RUN: not llvm-as < %s 2>&1 | FileCheck --check-prefix=ERROR %s
+
+; CHECK: !llvm.linker.options = !{!2, !3}
+; CHECK: !2 = !{!"/DEFAULTLIB:libcmtd.lib"}
+; CHECK: !3 = !{!"/DEFAULTLIB:oldnames.lib"}
+
+; ERROR: 'Linker Options' named metadata no longer supported
+
+!0 = !{i32 6, !"Linker Options", !1}
+!1 = !{!2, !3}
+!2 = !{!"/DEFAULTLIB:libcmtd.lib"}
+!3 = !{!"/DEFAULTLIB:oldnames.lib"}
+
+!llvm.module.flags = !{!0}
diff --git a/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir b/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir
index c806b4a7060d..ce913d211ae2 100644
--- a/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir
+++ b/test/CodeGen/AArch64/GlobalISel/legalize-load-store.mir
@@ -53,9 +53,7 @@ body: |
; CHECK: %7(<2 x s32>) = G_LOAD %0(p0) :: (load 8 from %ir.addr)
%7(<2 x s32>) = G_LOAD %0(p0) :: (load 8 from %ir.addr)
- ; CHECK: [[OFFSET0:%[0-9]+]](s64) = G_CONSTANT i64 0
- ; CHECK: [[GEP0:%[0-9]+]](p0) = G_GEP %0, [[OFFSET0]](s64)
- ; CHECK: [[LOAD0:%[0-9]+]](s64) = G_LOAD [[GEP0]](p0) :: (load 16 from %ir.addr)
+ ; CHECK: [[LOAD0:%[0-9]+]](s64) = G_LOAD %0(p0) :: (load 16 from %ir.addr)
; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 8
; CHECK: [[GEP1:%[0-9]+]](p0) = G_GEP %0, [[OFFSET1]](s64)
; CHECK: [[LOAD1:%[0-9]+]](s64) = G_LOAD [[GEP1]](p0) :: (load 16 from %ir.addr)
@@ -105,9 +103,7 @@ body: |
; CHECK: G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr)
G_STORE %0(p0), %0(p0) :: (store 8 into %ir.addr)
- ; CHECK: [[OFFSET0:%[0-9]+]](s64) = G_CONSTANT i64 0
- ; CHECK: [[GEP0:%[0-9]+]](p0) = G_GEP %0, [[OFFSET0]](s64)
- ; CHECK: G_STORE %5(s64), [[GEP0]](p0) :: (store 16 into %ir.addr)
+ ; CHECK: G_STORE %5(s64), %0(p0) :: (store 16 into %ir.addr)
; CHECK: [[OFFSET1:%[0-9]+]](s64) = G_CONSTANT i64 8
; CHECK: [[GEP1:%[0-9]+]](p0) = G_GEP %0, [[OFFSET1]](s64)
; CHECK: G_STORE %6(s64), [[GEP1]](p0) :: (store 16 into %ir.addr)
diff --git a/test/CodeGen/AArch64/arm64-sincos.ll b/test/CodeGen/AArch64/arm64-sincos.ll
index 06157b2580c4..98876dbe87b0 100644
--- a/test/CodeGen/AArch64/arm64-sincos.ll
+++ b/test/CodeGen/AArch64/arm64-sincos.ll
@@ -1,7 +1,9 @@
; RUN: llc < %s -mtriple=arm64-apple-ios7 | FileCheck %s --check-prefix CHECK-IOS
; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s --check-prefix CHECK-LINUX
-; Combine sin / cos into a single call.
+; Combine sin / cos into a single call unless they may write errno (as
+; captured by readnone attrbiute, controlled by clang -fmath-errno
+; setting).
; rdar://12856873
define float @test1(float %x) nounwind {
@@ -11,11 +13,26 @@ entry:
; CHECK-IOS: fadd s0, s0, s1
; CHECK-LINUX-LABEL: test1:
+; CHECK-LINUX: bl sincosf
+
+ %call = tail call float @sinf(float %x) readnone
+ %call1 = tail call float @cosf(float %x) readnone
+ %add = fadd float %call, %call1
+ ret float %add
+}
+
+define float @test1_errno(float %x) nounwind {
+entry:
+; CHECK-IOS-LABEL: test1_errno:
+; CHECK-IOS: bl _sinf
+; CHECK-IOS: bl _cosf
+
+; CHECK-LINUX-LABEL: test1_errno:
; CHECK-LINUX: bl sinf
; CHECK-LINUX: bl cosf
- %call = tail call float @sinf(float %x) nounwind readnone
- %call1 = tail call float @cosf(float %x) nounwind readnone
+ %call = tail call float @sinf(float %x)
+ %call1 = tail call float @cosf(float %x)
%add = fadd float %call, %call1
ret float %add
}
@@ -27,16 +44,31 @@ entry:
; CHECK-IOS: fadd d0, d0, d1
; CHECK-LINUX-LABEL: test2:
+; CHECK-LINUX: bl sincos
+
+ %call = tail call double @sin(double %x) readnone
+ %call1 = tail call double @cos(double %x) readnone
+ %add = fadd double %call, %call1
+ ret double %add
+}
+
+define double @test2_errno(double %x) nounwind {
+entry:
+; CHECK-IOS-LABEL: test2_errno:
+; CHECK-IOS: bl _sin
+; CHECK-IOS: bl _cos
+
+; CHECK-LINUX-LABEL: test2_errno:
; CHECK-LINUX: bl sin
; CHECK-LINUX: bl cos
- %call = tail call double @sin(double %x) nounwind readnone
- %call1 = tail call double @cos(double %x) nounwind readnone
+ %call = tail call double @sin(double %x)
+ %call1 = tail call double @cos(double %x)
%add = fadd double %call, %call1
ret double %add
}
-declare float @sinf(float) readonly
-declare double @sin(double) readonly
-declare float @cosf(float) readonly
-declare double @cos(double) readonly
+declare float @sinf(float)
+declare double @sin(double)
+declare float @cosf(float)
+declare double @cos(double)
diff --git a/test/CodeGen/AArch64/fast-isel-sp-adjust.ll b/test/CodeGen/AArch64/fast-isel-sp-adjust.ll
new file mode 100644
index 000000000000..9201d1be6a9c
--- /dev/null
+++ b/test/CodeGen/AArch64/fast-isel-sp-adjust.ll
@@ -0,0 +1,288 @@
+; RUN: llc -O0 -mtriple=aarch64-apple-ios -o - %s | FileCheck %s
+; RUN: not llc -O0 -mtriple=aarch64-apple-ios -o /dev/null -fast-isel-abort=3 %s 2> %t
+; RUN: FileCheck %s --check-prefix=CHECK-ERRORS < %t
+
+; The issue here is that FastISel cannot emit an ADDrr where one of the inputs
+; is SP. This only ever crops up with function calls, and then only if the
+; argument is at an offset > 2^12 * size from SP.
+
+; If FastISel ever starts coping with this and emits an "add xD, sp, xM" it's
+; critical to check the encoding as well as the textual assembly. An ADDXrs with
+; SP as an operand will still print with SP, but will actually mean XZR.
+
+; CHECK-ERRORS: LLVM ERROR: FastISel missed call
+
+; CHECK-LABEL: foo:
+; CHECK-DAG: mov x[[SP:[0-9]+]], sp
+; CHECK-DAG: mov [[TMP:w[0-9]+]], #4104
+; CHECK: mov w[[OFFSET:[0-9]+]], [[TMP]]
+; CHECK: strb w0, [x[[SP]], x[[OFFSET]]]
+
+define void @foo(i8 %in) {
+ call void @bar(i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef, ; All regs gone.
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 32
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 64
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 128
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 256
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 512
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 1024
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 2048
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef,
+ i64 undef, i64 undef, i64 undef, i64 undef, ; sp + 4096
+ i64 undef, ; sp + 4104 (i.e. not uimm12 or uimm12 << 12).
+ i8 %in)
+ ret void
+}
+
+declare void @bar(i64, i64, i64, i64,
+ i64, i64, i64, i64, ; All regs gone.
+ i64, i64, i64, i64, ; sp + 32
+ i64, i64, i64, i64, ; sp + 64
+ i64, i64, i64, i64,
+ i64, i64, i64, i64, ; sp + 128
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64, ; sp + 256
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64, ; sp + 512
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64, ; sp + 1024
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64, ; sp + 2048
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64,
+ i64, i64, i64, i64, ; sp + 4096
+ i64,
+ i8)
diff --git a/test/CodeGen/AArch64/misched-fusion-aes.ll b/test/CodeGen/AArch64/misched-fusion-aes.ll
index bd7c69c910c0..8ee4dbcee52b 100644
--- a/test/CodeGen/AArch64/misched-fusion-aes.ll
+++ b/test/CodeGen/AArch64/misched-fusion-aes.ll
@@ -1,7 +1,9 @@
-; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a53 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX
-; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX
-; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a72 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX
-; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a73 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKCORTEX
+; RUN: llc %s -o - -mtriple=aarch64-unknown -mattr=+fuse-aes,+crypto | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS
+; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=generic -mattr=+crypto | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS
+; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a53 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS
+; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a57 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS
+; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a72 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS
+; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=cortex-a73 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKFUSEALLPAIRS
; RUN: llc %s -o - -mtriple=aarch64-unknown -mcpu=exynos-m1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECKM1
declare <16 x i8> @llvm.aarch64.crypto.aese(<16 x i8> %d, <16 x i8> %k)
@@ -74,22 +76,23 @@ define void @aesea(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d,
ret void
; CHECK-LABEL: aesea:
-; CHECKCORTEX: aese [[VA:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VA]]
-; CHECKCORTEX: aese [[VB:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VB]]
-; CHECKCORTEX: aese [[VC:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VC]]
-; CHECKCORTEX: aese [[VD:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VD]]
-; CHECKCORTEX: aese [[VE:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VE]]
-; CHECKCORTEX: aese [[VF:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VF]]
-; CHECKCORTEX: aese [[VG:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VG]]
-; CHECKCORTEX: aese [[VH:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesmc {{v[0-7].16b}}, [[VH]]
+; CHECKFUSEALLPAIRS: aese [[VA:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VA]]
+; CHECKFUSEALLPAIRS: aese [[VB:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VB]]
+; CHECKFUSEALLPAIRS: aese [[VC:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VC]]
+; CHECKFUSEALLPAIRS: aese [[VD:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VD]]
+; CHECKFUSEALLPAIRS: aese [[VE:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VE]]
+; CHECKFUSEALLPAIRS: aese [[VF:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VF]]
+; CHECKFUSEALLPAIRS: aese [[VG:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VG]]
+; CHECKFUSEALLPAIRS: aese [[VH:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesmc {{v[0-7].16b}}, [[VH]]
+; CHECKFUSEALLPAIRS-NOT: aesmc
; CHECKM1: aese [[VA:v[0-7].16b]], {{v[0-7].16b}}
; CHECKM1-NEXT: aesmc {{v[0-7].16b}}, [[VA]]
@@ -175,22 +178,23 @@ define void @aesda(<16 x i8>* %a0, <16 x i8>* %b0, <16 x i8>* %c0, <16 x i8> %d,
ret void
; CHECK-LABEL: aesda:
-; CHECKCORTEX: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VA]]
-; CHECKCORTEX: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VB]]
-; CHECKCORTEX: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VC]]
-; CHECKCORTEX: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VD]]
-; CHECKCORTEX: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VE]]
-; CHECKCORTEX: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VF]]
-; CHECKCORTEX: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VG]]
-; CHECKCORTEX: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}}
-; CHECKCORTEX-NEXT: aesimc {{v[0-7].16b}}, [[VH]]
+; CHECKFUSEALLPAIRS: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VA]]
+; CHECKFUSEALLPAIRS: aesd [[VB:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VB]]
+; CHECKFUSEALLPAIRS: aesd [[VC:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VC]]
+; CHECKFUSEALLPAIRS: aesd [[VD:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VD]]
+; CHECKFUSEALLPAIRS: aesd [[VE:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VE]]
+; CHECKFUSEALLPAIRS: aesd [[VF:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VF]]
+; CHECKFUSEALLPAIRS: aesd [[VG:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VG]]
+; CHECKFUSEALLPAIRS: aesd [[VH:v[0-7].16b]], {{v[0-7].16b}}
+; CHECKFUSEALLPAIRS-NEXT: aesimc {{v[0-7].16b}}, [[VH]]
+; CHECKFUSEALLPAIRS-NOT: aesimc
; CHECKM1: aesd [[VA:v[0-7].16b]], {{v[0-7].16b}}
; CHECKM1-NEXT: aesimc {{v[0-7].16b}}, [[VA]]
@@ -236,4 +240,5 @@ entry:
; CHECK-NEXT: aesmc {{v[0-7].16b}}, [[VA]]
; CHECK: aese [[VB:v[0-7].16b]], {{v[0-7].16b}}
; CHECK-NEXT: aesmc {{v[0-7].16b}}, [[VB]]
+; CHECK-NOT: aesmc
}
diff --git a/test/CodeGen/AArch64/sincos-expansion.ll b/test/CodeGen/AArch64/sincos-expansion.ll
index c3a172dfb427..41ee40378b4f 100644
--- a/test/CodeGen/AArch64/sincos-expansion.ll
+++ b/test/CodeGen/AArch64/sincos-expansion.ll
@@ -1,8 +1,18 @@
; RUN: llc -mtriple=aarch64-linux-gnu -verify-machineinstrs -o - %s | FileCheck %s
define float @test_sincos_f32(float %f) {
+; CHECK-LABEL: test_sincos_f32:
%sin = call float @sinf(float %f) readnone
%cos = call float @cosf(float %f) readnone
+; CHECK: bl sincosf
+ %val = fadd float %sin, %cos
+ ret float %val
+}
+
+define float @test_sincos_f32_errno(float %f) {
+; CHECK-LABEL: test_sincos_f32_errno:
+ %sin = call float @sinf(float %f)
+ %cos = call float @cosf(float %f)
; CHECK: bl sinf
; CHECK: bl cosf
%val = fadd float %sin, %cos
@@ -10,26 +20,46 @@ define float @test_sincos_f32(float %f) {
}
define double @test_sincos_f64(double %f) {
+; CHECK-LABEL: test_sincos_f64:
%sin = call double @sin(double %f) readnone
%cos = call double @cos(double %f) readnone
%val = fadd double %sin, %cos
+; CHECK: bl sincos
+ ret double %val
+}
+
+define double @test_sincos_f64_errno(double %f) {
+; CHECK-LABEL: test_sincos_f64_errno:
+ %sin = call double @sin(double %f)
+ %cos = call double @cos(double %f)
+ %val = fadd double %sin, %cos
; CHECK: bl sin
; CHECK: bl cos
ret double %val
}
define fp128 @test_sincos_f128(fp128 %f) {
+; CHECK-LABEL: test_sincos_f128:
%sin = call fp128 @sinl(fp128 %f) readnone
%cos = call fp128 @cosl(fp128 %f) readnone
%val = fadd fp128 %sin, %cos
+; CHECK: bl sincosl
+ ret fp128 %val
+}
+
+define fp128 @test_sincos_f128_errno(fp128 %f) {
+; CHECK-LABEL: test_sincos_f128_errno:
+ %sin = call fp128 @sinl(fp128 %f)
+ %cos = call fp128 @cosl(fp128 %f)
+ %val = fadd fp128 %sin, %cos
; CHECK: bl sinl
; CHECK: bl cosl
ret fp128 %val
}
-declare float @sinf(float) readonly
-declare double @sin(double) readonly
-declare fp128 @sinl(fp128) readonly
-declare float @cosf(float) readonly
-declare double @cos(double) readonly
-declare fp128 @cosl(fp128) readonly
+declare float @sinf(float)
+declare double @sin(double)
+declare fp128 @sinl(fp128)
+declare float @cosf(float)
+declare double @cos(double)
+declare fp128 @cosl(fp128)
diff --git a/test/CodeGen/AArch64/swifterror.ll b/test/CodeGen/AArch64/swifterror.ll
index 69bf3510cc5a..bc28f477c810 100644
--- a/test/CodeGen/AArch64/swifterror.ll
+++ b/test/CodeGen/AArch64/swifterror.ll
@@ -597,3 +597,30 @@ entry:
tail call void @acallee(i8* null)
ret void
}
+
+declare swiftcc void @foo2(%swift_error** swifterror)
+
+; Make sure we properly assign registers during fast-isel.
+; CHECK-O0-LABEL: testAssign
+; CHECK-O0: mov [[TMP:x.*]], xzr
+; CHECK-O0: mov x21, [[TMP]]
+; CHECK-O0: bl _foo2
+; CHECK-O0: str x21, [s[[STK:.*]]]
+; CHECK-O0: ldr x0, [s[[STK]]]
+
+; CHECK-APPLE-LABEL: testAssign
+; CHECK-APPLE: mov x21, xzr
+; CHECK-APPLE: bl _foo2
+; CHECK-APPLE: mov x0, x21
+
+define swiftcc %swift_error* @testAssign(i8* %error_ref) {
+entry:
+ %error_ptr = alloca swifterror %swift_error*
+ store %swift_error* null, %swift_error** %error_ptr
+ call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
+ br label %a
+
+a:
+ %error = load %swift_error*, %swift_error** %error_ptr
+ ret %swift_error* %error
+}
diff --git a/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir b/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir
index 2a3d3887ed69..56a9e7022db9 100644
--- a/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir
+++ b/test/CodeGen/AMDGPU/GlobalISel/inst-select-load-flat.mir
@@ -14,7 +14,7 @@ regBankSelected: true
# GCN: global_addrspace
# GCN: [[PTR:%[0-9]+]] = COPY %vgpr0_vgpr1
-# GCN: FLAT_LOAD_DWORD [[PTR]], 0, 0
+# GCN: FLAT_LOAD_DWORD [[PTR]], 0, 0, 0
body: |
bb.0:
diff --git a/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir b/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir
index 89be3bde94a8..ea435725bf25 100644
--- a/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir
+++ b/test/CodeGen/AMDGPU/GlobalISel/inst-select-store-flat.mir
@@ -15,7 +15,7 @@ regBankSelected: true
# GCN: global_addrspace
# GCN: [[PTR:%[0-9]+]] = COPY %vgpr0_vgpr1
# GCN: [[VAL:%[0-9]+]] = COPY %vgpr2
-# GCN: FLAT_STORE_DWORD [[PTR]], [[VAL]], 0, 0
+# GCN: FLAT_STORE_DWORD [[PTR]], [[VAL]], 0, 0, 0
body: |
bb.0:
diff --git a/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir b/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir
new file mode 100644
index 000000000000..f10c896a7af6
--- /dev/null
+++ b/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir
@@ -0,0 +1,22 @@
+# RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=fiji -O0 -run-pass=legalizer -global-isel %s -o - | FileCheck %s
+
+--- |
+ define void @test_add() { ret void }
+...
+
+---
+name: test_add
+registers:
+ - { id: 0, class: _ }
+ - { id: 1, class: _ }
+ - { id: 2, class: _ }
+body: |
+ bb.0:
+ liveins: %vgpr0, %vgpr1
+ ; CHECK-LABEL: name: test_add
+ ; CHECK: %2(s32) = G_ADD %0, %1
+
+ %0(s32) = COPY %vgpr0
+ %1(s32) = COPY %vgpr1
+ %2(s32) = G_ADD %0, %1
+...
diff --git a/test/CodeGen/AMDGPU/always-uniform.ll b/test/CodeGen/AMDGPU/always-uniform.ll
new file mode 100644
index 000000000000..4ba57fba81bc
--- /dev/null
+++ b/test/CodeGen/AMDGPU/always-uniform.ll
@@ -0,0 +1,21 @@
+; RUN: llc -mtriple amdgcn-amdhsa -mcpu=fiji -amdgpu-scalarize-global-loads -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
+
+declare i32 @llvm.amdgcn.workitem.id.x()
+declare i32 @llvm.amdgcn.readfirstlane(i32)
+
+; GCN-LABEL: readfirstlane_uniform
+; GCN: s_load_dwordx2 s{{\[}}[[IN_ADDR:[0-9]+]]:1{{\]}}, s[4:5], 0x0
+; GCN: v_readfirstlane_b32 s[[SCALAR:[0-9]+]], v0
+; GCN: s_add_u32 s[[LOAD_ADDR:[0-9]+]], s[[IN_ADDR]], s[[SCALAR]]
+; GCN: s_load_dword s{{[0-9]+}}, s{{\[}}[[LOAD_ADDR]]
+
+define amdgpu_kernel void @readfirstlane_uniform(float addrspace(1)* noalias nocapture readonly, float addrspace(1)* noalias nocapture readonly) {
+ %tid = tail call i32 @llvm.amdgcn.workitem.id.x()
+ %scalar = tail call i32 @llvm.amdgcn.readfirstlane(i32 %tid)
+ %idx = zext i32 %scalar to i64
+ %gep0 = getelementptr inbounds float, float addrspace(1)* %0, i64 %idx
+ %val = load float, float addrspace(1)* %gep0, align 4
+ %gep1 = getelementptr inbounds float, float addrspace(1)* %1, i64 10
+ store float %val, float addrspace(1)* %gep1, align 4
+ ret void
+}
diff --git a/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll b/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll
index cbdcf6aeaf42..5dec3e35ab3d 100644
--- a/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll
+++ b/test/CodeGen/AMDGPU/cgp-addressing-modes-flat.ll
@@ -1,12 +1,19 @@
-; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=bonaire < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-CI %s
-; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-VI %s
-; RUN: llc -march=amdgcn -mcpu=bonaire -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=CI %s
-; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=VI %s
+; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=bonaire < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-CI -check-prefix=OPT-CIVI %s
+; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-VI -check-prefix=OPT-CIVI %s
+; RUN: opt -S -codegenprepare -mtriple=amdgcn-unknown-unknown -mcpu=gfx900 -mattr=-flat-for-global < %s | FileCheck -check-prefix=OPT -check-prefix=OPT-GFX9 %s
+; RUN: llc -march=amdgcn -mcpu=bonaire -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=CI -check-prefix=CIVI %s
+; RUN: llc -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=VI -check-prefix=CIVI %s
+; RUN: llc -march=amdgcn -mcpu=gfx900 -mattr=-flat-for-global -mattr=-promote-alloca < %s | FileCheck -check-prefix=GCN -check-prefix=GFX9 %s
; OPT-LABEL: @test_no_sink_flat_small_offset_i32(
-; OPT: getelementptr i32, i32 addrspace(4)* %in
-; OPT: br i1
-; OPT-NOT: ptrtoint
+; OPT-CIVI: getelementptr i32, i32 addrspace(4)* %in
+; OPT-CIVI: br i1
+; OPT-CIVI-NOT: ptrtoint
+
+; OPT-GFX9: br
+; OPT-GFX9: %sunkaddr = getelementptr i8, i8 addrspace(4)* %0, i64 28
+; OPT-GFX9: %1 = bitcast i8 addrspace(4)* %sunkaddr to i32 addrspace(4)*
+; OPT-GFX9: load i32, i32 addrspace(4)* %1
; GCN-LABEL: {{^}}test_no_sink_flat_small_offset_i32:
; GCN: flat_load_dword
@@ -96,3 +103,105 @@ endif:
done:
ret void
}
+
+; OPT-LABEL: @test_sink_flat_small_max_flat_offset(
+; OPT-CIVI: %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4095
+; OPT-CIVI: br
+; OPT-CIVI-NOT: getelementptr
+; OPT-CIVI: load i8, i8 addrspace(4)* %in.gep
+
+; OPT-GFX9: br
+; OPT-GFX9: %sunkaddr = getelementptr i8, i8 addrspace(4)* %in, i64 4095
+; OPT-GFX9: load i8, i8 addrspace(4)* %sunkaddr
+
+; GCN-LABEL: {{^}}test_sink_flat_small_max_flat_offset:
+; GFX9: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}} offset:4095{{$}}
+; CIVI: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]$}}
+define amdgpu_kernel void @test_sink_flat_small_max_flat_offset(i32 addrspace(4)* %out, i8 addrspace(4)* %in) #1 {
+entry:
+ %out.gep = getelementptr i32, i32 addrspace(4)* %out, i32 1024
+ %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4095
+ %tid = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #0
+ %tmp0 = icmp eq i32 %tid, 0
+ br i1 %tmp0, label %endif, label %if
+
+if:
+ %tmp1 = load i8, i8 addrspace(4)* %in.gep
+ %tmp2 = sext i8 %tmp1 to i32
+ br label %endif
+
+endif:
+ %x = phi i32 [ %tmp2, %if ], [ 0, %entry ]
+ store i32 %x, i32 addrspace(4)* %out.gep
+ br label %done
+
+done:
+ ret void
+}
+
+; OPT-LABEL: @test_sink_flat_small_max_plus_1_flat_offset(
+; OPT: %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4096
+; OPT: br
+; OPT-NOT: getelementptr
+; OPT: load i8, i8 addrspace(4)* %in.gep
+
+; GCN-LABEL: {{^}}test_sink_flat_small_max_plus_1_flat_offset:
+; GCN: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]$}}
+define amdgpu_kernel void @test_sink_flat_small_max_plus_1_flat_offset(i32 addrspace(4)* %out, i8 addrspace(4)* %in) #1 {
+entry:
+ %out.gep = getelementptr i32, i32 addrspace(4)* %out, i64 99999
+ %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 4096
+ %tid = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #0
+ %tmp0 = icmp eq i32 %tid, 0
+ br i1 %tmp0, label %endif, label %if
+
+if:
+ %tmp1 = load i8, i8 addrspace(4)* %in.gep
+ %tmp2 = sext i8 %tmp1 to i32
+ br label %endif
+
+endif:
+ %x = phi i32 [ %tmp2, %if ], [ 0, %entry ]
+ store i32 %x, i32 addrspace(4)* %out.gep
+ br label %done
+
+done:
+ ret void
+}
+
+; OPT-LABEL: @test_no_sink_flat_reg_offset(
+; OPT: %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 %reg
+; OPT: br
+
+; OPT-NOT: getelementptr
+; OPT: load i8, i8 addrspace(4)* %in.gep
+
+; GCN-LABEL: {{^}}test_no_sink_flat_reg_offset:
+; GCN: flat_load_sbyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]$}}
+define amdgpu_kernel void @test_no_sink_flat_reg_offset(i32 addrspace(4)* %out, i8 addrspace(4)* %in, i64 %reg) #1 {
+entry:
+ %out.gep = getelementptr i32, i32 addrspace(4)* %out, i32 1024
+ %in.gep = getelementptr i8, i8 addrspace(4)* %in, i64 %reg
+ %tid = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #0
+ %tmp0 = icmp eq i32 %tid, 0
+ br i1 %tmp0, label %endif, label %if
+
+if:
+ %tmp1 = load i8, i8 addrspace(4)* %in.gep
+ %tmp2 = sext i8 %tmp1 to i32
+ br label %endif
+
+endif:
+ %x = phi i32 [ %tmp2, %if ], [ 0, %entry ]
+ store i32 %x, i32 addrspace(4)* %out.gep
+ br label %done
+
+done:
+ ret void
+}
+
+declare i32 @llvm.amdgcn.mbcnt.lo(i32, i32) #0
+
+attributes #0 = { nounwind readnone }
+attributes #1 = { nounwind }
+attributes #2 = { nounwind argmemonly }
diff --git a/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll b/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll
index 801029be8cb9..0796c24b3317 100644
--- a/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll
+++ b/test/CodeGen/AMDGPU/code-object-metadata-kernel-debug-props.ll
@@ -12,7 +12,9 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
; CHECK: DebugProps:
; CHECK: DebuggerABIVersion: [ 1, 0 ]
; CHECK: ReservedNumVGPRs: 4
-; CHECK: ReservedFirstVGPR: 11
+; GFX700: ReservedFirstVGPR: 11
+; GFX800: ReservedFirstVGPR: 11
+; GFX9: ReservedFirstVGPR: 14
; CHECK: PrivateSegmentBufferSGPR: 0
; CHECK: WavefrontPrivateSegmentOffsetSGPR: 11
define amdgpu_kernel void @test(i32 addrspace(1)* %A) #0 !dbg !7 !kernel_arg_addr_space !12 !kernel_arg_access_qual !13 !kernel_arg_type !14 !kernel_arg_base_type !14 !kernel_arg_type_qual !15 {
diff --git a/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir b/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir
index bc992ed77ffd..62b47beb1251 100644
--- a/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir
+++ b/test/CodeGen/AMDGPU/constant-fold-imm-immreg.mir
@@ -219,19 +219,19 @@ body: |
%34 = V_MOV_B32_e32 63, implicit %exec
%27 = V_AND_B32_e64 %26, %24, implicit %exec
- FLAT_STORE_DWORD %37, %27, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %37, %27, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%28 = V_AND_B32_e64 %24, %26, implicit %exec
- FLAT_STORE_DWORD %37, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %37, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%29 = V_AND_B32_e32 %26, %24, implicit %exec
- FLAT_STORE_DWORD %37, %29, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %37, %29, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%30 = V_AND_B32_e64 %26, %26, implicit %exec
- FLAT_STORE_DWORD %37, %30, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %37, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%31 = V_AND_B32_e64 %34, %34, implicit %exec
- FLAT_STORE_DWORD %37, %31, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %37, %31, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
S_ENDPGM
@@ -407,34 +407,34 @@ body: |
%27 = S_MOV_B32 -4
%11 = V_LSHLREV_B32_e64 12, %10, implicit %exec
- FLAT_STORE_DWORD %20, %11, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %11, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%12 = V_LSHLREV_B32_e64 %7, 12, implicit %exec
- FLAT_STORE_DWORD %20, %12, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %12, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%13 = V_LSHL_B32_e64 %7, 12, implicit %exec
- FLAT_STORE_DWORD %20, %13, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %13, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%14 = V_LSHL_B32_e64 12, %7, implicit %exec
- FLAT_STORE_DWORD %20, %14, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %14, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%15 = V_LSHL_B32_e64 12, %24, implicit %exec
- FLAT_STORE_DWORD %20, %15, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %15, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%22 = V_LSHL_B32_e64 %6, 12, implicit %exec
- FLAT_STORE_DWORD %20, %22, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %22, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%23 = V_LSHL_B32_e64 %6, 32, implicit %exec
- FLAT_STORE_DWORD %20, %23, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %23, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%25 = V_LSHL_B32_e32 %6, %6, implicit %exec
- FLAT_STORE_DWORD %20, %25, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %25, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%26 = V_LSHLREV_B32_e32 11, %24, implicit %exec
- FLAT_STORE_DWORD %20, %26, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %26, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%28 = V_LSHL_B32_e32 %27, %6, implicit %exec
- FLAT_STORE_DWORD %20, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
S_ENDPGM
@@ -615,34 +615,34 @@ body: |
%35 = V_MOV_B32_e32 2, implicit %exec
%11 = V_ASHRREV_I32_e64 8, %10, implicit %exec
- FLAT_STORE_DWORD %20, %11, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %11, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%12 = V_ASHRREV_I32_e64 %8, %10, implicit %exec
- FLAT_STORE_DWORD %20, %12, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %12, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%13 = V_ASHR_I32_e64 %7, 3, implicit %exec
- FLAT_STORE_DWORD %20, %13, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %13, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%14 = V_ASHR_I32_e64 7, %32, implicit %exec
- FLAT_STORE_DWORD %20, %14, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %14, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%15 = V_ASHR_I32_e64 %27, %24, implicit %exec
- FLAT_STORE_DWORD %20, %15, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %15, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%22 = V_ASHR_I32_e64 %6, 4, implicit %exec
- FLAT_STORE_DWORD %20, %22, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %22, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%23 = V_ASHR_I32_e64 %6, %33, implicit %exec
- FLAT_STORE_DWORD %20, %23, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %23, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%25 = V_ASHR_I32_e32 %34, %34, implicit %exec
- FLAT_STORE_DWORD %20, %25, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %25, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%26 = V_ASHRREV_I32_e32 11, %10, implicit %exec
- FLAT_STORE_DWORD %20, %26, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %26, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%28 = V_ASHR_I32_e32 %27, %35, implicit %exec
- FLAT_STORE_DWORD %20, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
S_ENDPGM
@@ -824,34 +824,34 @@ body: |
%35 = V_MOV_B32_e32 2, implicit %exec
%11 = V_LSHRREV_B32_e64 8, %10, implicit %exec
- FLAT_STORE_DWORD %20, %11, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %11, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%12 = V_LSHRREV_B32_e64 %8, %10, implicit %exec
- FLAT_STORE_DWORD %20, %12, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %12, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%13 = V_LSHR_B32_e64 %7, 3, implicit %exec
- FLAT_STORE_DWORD %20, %13, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %13, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%14 = V_LSHR_B32_e64 7, %32, implicit %exec
- FLAT_STORE_DWORD %20, %14, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %14, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%15 = V_LSHR_B32_e64 %27, %24, implicit %exec
- FLAT_STORE_DWORD %20, %15, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %15, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%22 = V_LSHR_B32_e64 %6, 4, implicit %exec
- FLAT_STORE_DWORD %20, %22, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %22, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%23 = V_LSHR_B32_e64 %6, %33, implicit %exec
- FLAT_STORE_DWORD %20, %23, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %23, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%25 = V_LSHR_B32_e32 %34, %34, implicit %exec
- FLAT_STORE_DWORD %20, %25, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %25, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%26 = V_LSHRREV_B32_e32 11, %10, implicit %exec
- FLAT_STORE_DWORD %20, %26, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %26, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
%28 = V_LSHR_B32_e32 %27, %35, implicit %exec
- FLAT_STORE_DWORD %20, %28, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
+ FLAT_STORE_DWORD %20, %28, 0, 0, 0, implicit %exec, implicit %flat_scr :: (volatile store 4 into %ir.gep.out)
S_ENDPGM
diff --git a/test/CodeGen/AMDGPU/flat-address-space.ll b/test/CodeGen/AMDGPU/flat-address-space.ll
index c867e4fca229..e486b9c71a54 100644
--- a/test/CodeGen/AMDGPU/flat-address-space.ll
+++ b/test/CodeGen/AMDGPU/flat-address-space.ll
@@ -1,6 +1,7 @@
-; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=bonaire < %s | FileCheck %s
-; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck %s
+; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=bonaire < %s | FileCheck -check-prefixes=CHECK,CIVI %s
+; RUN: llc -O0 -mtriple=amdgcn-mesa-mesa3d -mcpu=tonga -mattr=-flat-for-global < %s | FileCheck -check-prefixes=CHECK,CIVI %s
; RUN: llc -O0 -mtriple=amdgcn-amd-amdhsa -mcpu=fiji -mattr=-flat-for-global < %s | FileCheck -check-prefixes=CHECK,HSA %s
+; RUN: llc -O0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -mattr=-flat-for-global < %s | FileCheck -check-prefixes=CHECK,HSA,GFX9 %s
; Disable optimizations in case there are optimizations added that
; specialize away generic pointer accesses.
@@ -172,6 +173,55 @@ define amdgpu_kernel void @flat_scratch_multidword_store() {
ret void
}
+; CHECK-LABEL: {{^}}store_flat_i8_max_offset:
+; CIVI: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}}{{$}}
+; GFX9: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}} offset:4095{{$}}
+define amdgpu_kernel void @store_flat_i8_max_offset(i8 addrspace(4)* %fptr, i8 %x) #0 {
+ %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4095
+ store volatile i8 %x, i8 addrspace(4)* %fptr.offset
+ ret void
+}
+
+; CHECK-LABEL: {{^}}store_flat_i8_max_offset_p1:
+; CHECK: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}}{{$}}
+define amdgpu_kernel void @store_flat_i8_max_offset_p1(i8 addrspace(4)* %fptr, i8 %x) #0 {
+ %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4096
+ store volatile i8 %x, i8 addrspace(4)* %fptr.offset
+ ret void
+}
+
+; CHECK-LABEL: {{^}}store_flat_i8_neg_offset:
+; CHECK: flat_store_byte v{{\[[0-9]+:[0-9]+\]}}, v{{[0-9]+}}{{$}}
+define amdgpu_kernel void @store_flat_i8_neg_offset(i8 addrspace(4)* %fptr, i8 %x) #0 {
+ %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 -2
+ store volatile i8 %x, i8 addrspace(4)* %fptr.offset
+ ret void
+}
+
+; CHECK-LABEL: {{^}}load_flat_i8_max_offset:
+; CIVI: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}}{{$}}
+; GFX9: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}} offset:4095{{$}}
+define amdgpu_kernel void @load_flat_i8_max_offset(i8 addrspace(4)* %fptr) #0 {
+ %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4095
+ %val = load volatile i8, i8 addrspace(4)* %fptr.offset
+ ret void
+}
+
+; CHECK-LABEL: {{^}}load_flat_i8_max_offset_p1:
+; CHECK: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}}{{$}}
+define amdgpu_kernel void @load_flat_i8_max_offset_p1(i8 addrspace(4)* %fptr) #0 {
+ %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 4096
+ %val = load volatile i8, i8 addrspace(4)* %fptr.offset
+ ret void
+}
+
+; CHECK-LABEL: {{^}}load_flat_i8_neg_offset:
+; CHECK: flat_load_ubyte v{{[0-9]+}}, v{{\[[0-9]+:[0-9]+\]}}{{$}}
+define amdgpu_kernel void @load_flat_i8_neg_offset(i8 addrspace(4)* %fptr) #0 {
+ %fptr.offset = getelementptr inbounds i8, i8 addrspace(4)* %fptr, i64 -2
+ %val = load volatile i8, i8 addrspace(4)* %fptr.offset
+ ret void
+}
+
attributes #0 = { nounwind }
attributes #1 = { nounwind convergent }
-attributes #3 = { nounwind readnone }
diff --git a/test/CodeGen/AMDGPU/flat_atomics.ll b/test/CodeGen/AMDGPU/flat_atomics.ll
index cc95d80570e0..8e153181decb 100644
--- a/test/CodeGen/AMDGPU/flat_atomics.ll
+++ b/test/CodeGen/AMDGPU/flat_atomics.ll
@@ -1,8 +1,10 @@
-; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
-; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s
+; RUN: llc -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,CIVI %s
+; RUN: llc -march=amdgcn -mcpu=tonga -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,CIVI %s
+; RUN: llc -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -check-prefixes=GCN,GFX9 %s
; GCN-LABEL: {{^}}atomic_add_i32_offset:
-; GCN: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}}
+; CIVI: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}}
+; GFX9: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_add_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -10,8 +12,28 @@ entry:
ret void
}
+; GCN-LABEL: {{^}}atomic_add_i32_max_offset:
+; CIVI: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}}
+; GFX9: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:4092{{$}}
+define amdgpu_kernel void @atomic_add_i32_max_offset(i32 addrspace(4)* %out, i32 %in) {
+entry:
+ %gep = getelementptr i32, i32 addrspace(4)* %out, i32 1023
+ %val = atomicrmw volatile add i32 addrspace(4)* %gep, i32 %in seq_cst
+ ret void
+}
+
+; GCN-LABEL: {{^}}atomic_add_i32_max_offset_p1:
+; GCN: flat_atomic_add v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}}
+define amdgpu_kernel void @atomic_add_i32_max_offset_p1(i32 addrspace(4)* %out, i32 %in) {
+entry:
+ %gep = getelementptr i32, i32 addrspace(4)* %out, i32 1024
+ %val = atomicrmw volatile add i32 addrspace(4)* %gep, i32 %in seq_cst
+ ret void
+}
+
; GCN-LABEL: {{^}}atomic_add_i32_ret_offset:
-; GCN: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_add_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -22,7 +44,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_add_i32_addr64_offset:
-; GCN: flat_atomic_add v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_add v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_add v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_add_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -32,7 +55,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_add_i32_ret_addr64_offset:
-; GCN: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_add [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_add_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -82,7 +106,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_and_i32_offset:
-; GCN: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_and_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -91,7 +116,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_and_i32_ret_offset:
-; GCN: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_and_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -102,7 +128,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_and_i32_addr64_offset:
-; GCN: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_and v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_and_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -112,7 +139,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_and_i32_ret_addr64_offset:
-; GCN: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_and [[RET:v[0-9]]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_and_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -162,7 +190,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_sub_i32_offset:
-; GCN: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_sub_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -171,7 +200,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_sub_i32_ret_offset:
-; GCN: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_sub_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -182,7 +212,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_sub_i32_addr64_offset:
-; GCN: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_sub v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_sub_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -192,7 +223,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_sub_i32_ret_addr64_offset:
-; GCN: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_sub [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_sub_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -242,7 +274,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_max_i32_offset:
-; GCN: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_max_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -251,7 +284,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_max_i32_ret_offset:
-; GCN: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_max_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -262,7 +296,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_max_i32_addr64_offset:
-; GCN: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_smax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_max_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -272,7 +307,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_max_i32_ret_addr64_offset:
-; GCN: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_smax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_max_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -322,7 +358,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umax_i32_offset:
-; GCN: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_umax_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -331,7 +368,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umax_i32_ret_offset:
-; GCN: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_umax_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -342,7 +380,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umax_i32_addr64_offset:
-; GCN: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_umax v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_umax_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -352,7 +391,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umax_i32_ret_addr64_offset:
-; GCN: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_umax [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_umax_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -402,7 +442,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_min_i32_offset:
-; GCN: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_min_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -411,7 +452,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_min_i32_ret_offset:
-; GCN: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_min_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -422,7 +464,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_min_i32_addr64_offset:
-; GCN: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_smin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_min_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -432,7 +475,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_min_i32_ret_addr64_offset:
-; GCN: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_smin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_min_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -482,7 +526,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umin_i32_offset:
-; GCN: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_umin_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -491,7 +536,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umin_i32_ret_offset:
-; GCN: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_umin_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -502,7 +548,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umin_i32_addr64_offset:
-; GCN: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_umin v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_umin_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -512,7 +559,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_umin_i32_ret_addr64_offset:
-; GCN: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_umin [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_umin_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -562,7 +610,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_or_i32_offset:
-; GCN: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}}
+; CIVI: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_or_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -571,7 +620,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_or_i32_ret_offset:
-; GCN: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_or_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -582,7 +632,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_or_i32_addr64_offset:
-; GCN: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}}
+; CIVI: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_or v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_or_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -592,7 +643,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_or_i32_ret_addr64_offset:
-; GCN: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_or [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_or_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -642,7 +694,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xchg_i32_offset:
-; GCN: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}}
+; CIVI: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_xchg_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -651,7 +704,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xchg_i32_ret_offset:
-; GCN: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_xchg_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -662,7 +716,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xchg_i32_addr64_offset:
-; GCN: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}}{{$}}
+; CIVI: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_swap v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_xchg_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -672,7 +727,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xchg_i32_ret_addr64_offset:
-; GCN: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_swap [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_xchg_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -724,7 +780,8 @@ entry:
; CMP_SWAP
; GCN-LABEL: {{^}}atomic_cmpxchg_i32_offset:
-; GCN: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}}
+; CIVI: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}}
+; GFX9: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] offset:16{{$}}
define amdgpu_kernel void @atomic_cmpxchg_i32_offset(i32 addrspace(4)* %out, i32 %in, i32 %old) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -733,7 +790,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_cmpxchg_i32_ret_offset:
-; GCN: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}}
+; CIVI: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}}
+; GFX9: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, v[[RET]]
define amdgpu_kernel void @atomic_cmpxchg_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i32 %old) {
entry:
@@ -745,7 +803,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_cmpxchg_i32_addr64_offset:
-; GCN: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}}
+; CIVI: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}]{{$}}
+; GFX9: flat_atomic_cmpswap v[{{[0-9]+\:[0-9]+}}], v[{{[0-9]+}}:{{[0-9]+}}] offset:16{{$}}
define amdgpu_kernel void @atomic_cmpxchg_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index, i32 %old) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -755,7 +814,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_cmpxchg_i32_ret_addr64_offset:
-; GCN: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+:[0-9]+}}], v[{{[0-9]+:[0-9]+}}] glc{{$}}
+; CIVI: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+:[0-9]+}}], v[{{[0-9]+:[0-9]+}}] glc{{$}}
+; GFX9: flat_atomic_cmpswap v[[RET:[0-9]+]], v[{{[0-9]+:[0-9]+}}], v[{{[0-9]+:[0-9]+}}] offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, v[[RET]]
define amdgpu_kernel void @atomic_cmpxchg_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index, i32 %old) {
entry:
@@ -808,7 +868,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xor_i32_offset:
-; GCN: flat_atomic_xor v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}}
+; CIVI: flat_atomic_xor v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}}{{$}}
+; GFX9: flat_atomic_xor v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_xor_i32_offset(i32 addrspace(4)* %out, i32 %in) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -817,7 +878,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xor_i32_ret_offset:
-; GCN: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_xor_i32_ret_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in) {
entry:
@@ -828,7 +890,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xor_i32_addr64_offset:
-; GCN: flat_atomic_xor v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; CIVI: flat_atomic_xor v[{{[0-9]+:[0-9]+}}], v{{[0-9]+$}}
+; GFX9: flat_atomic_xor v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16{{$}}
define amdgpu_kernel void @atomic_xor_i32_addr64_offset(i32 addrspace(4)* %out, i32 %in, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
@@ -838,7 +901,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_xor_i32_ret_addr64_offset:
-; GCN: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; CIVI: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} glc{{$}}
+; GFX9: flat_atomic_xor [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}], v{{[0-9]+}} offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_xor_i32_ret_addr64_offset(i32 addrspace(4)* %out, i32 addrspace(4)* %out2, i32 %in, i64 %index) {
entry:
@@ -888,7 +952,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_load_i32_offset:
-; GCN: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}}
+; CIVI: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}] glc{{$}}
+; GFX9: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+}}:{{[0-9]+}}] offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_load_i32_offset(i32 addrspace(4)* %in, i32 addrspace(4)* %out) {
entry:
@@ -909,7 +974,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_load_i32_addr64_offset:
-; GCN: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}] glc{{$}}
+; CIVI: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}] glc{{$}}
+; GFX9: flat_load_dword [[RET:v[0-9]+]], v[{{[0-9]+:[0-9]+}}] offset:16 glc{{$}}
; GCN: flat_store_dword v{{\[[0-9]+:[0-9]+\]}}, [[RET]]
define amdgpu_kernel void @atomic_load_i32_addr64_offset(i32 addrspace(4)* %in, i32 addrspace(4)* %out, i64 %index) {
entry:
@@ -932,7 +998,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_store_i32_offset:
-; GCN: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}}
+; CIVI: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}}
+; GFX9: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} offset:16 glc{{$}}
define amdgpu_kernel void @atomic_store_i32_offset(i32 %in, i32 addrspace(4)* %out) {
entry:
%gep = getelementptr i32, i32 addrspace(4)* %out, i32 4
@@ -949,7 +1016,8 @@ entry:
}
; GCN-LABEL: {{^}}atomic_store_i32_addr64_offset:
-; GCN: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}}
+; CIVI: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} glc{{$}}
+; GFX9: flat_store_dword v[{{[0-9]+}}:{{[0-9]+}}], {{v[0-9]+}} offset:16 glc{{$}}
define amdgpu_kernel void @atomic_store_i32_addr64_offset(i32 %in, i32 addrspace(4)* %out, i64 %index) {
entry:
%ptr = getelementptr i32, i32 addrspace(4)* %out, i64 %index
diff --git a/test/CodeGen/AMDGPU/global_smrd_cfg.ll b/test/CodeGen/AMDGPU/global_smrd_cfg.ll
index a6a04151caa9..be6e3fd05ae7 100644
--- a/test/CodeGen/AMDGPU/global_smrd_cfg.ll
+++ b/test/CodeGen/AMDGPU/global_smrd_cfg.ll
@@ -72,6 +72,39 @@ bb22: ; preds = %bb20, %bb11
br i1 %tmp31, label %bb7, label %bb11
}
+; one more test to ensure that aliasing store after the load
+; is considered clobbering if load parent block is the same
+; as a loop header block.
+
+; CHECK-LABEL: %bb1
+
+; Load from %arg has alias store that is after the load
+; but is considered clobbering because of the loop.
+
+; CHECK: flat_load_dword
+
+define amdgpu_kernel void @cfg_selfloop(i32 addrspace(1)* nocapture readonly %arg, i32 addrspace(1)* nocapture %arg1, i32 %arg2) #0 {
+bb:
+ br label %bb1
+
+bb2:
+ ret void
+
+bb1:
+ %tmp13 = phi i32 [ %tmp25, %bb1 ], [ 0, %bb ]
+ %tmp14 = srem i32 %tmp13, %arg2
+ %tmp15 = sext i32 %tmp14 to i64
+ %tmp16 = getelementptr inbounds i32, i32 addrspace(1)* %arg, i64 %tmp15
+ %tmp17 = load i32, i32 addrspace(1)* %tmp16, align 4, !tbaa !0
+ %tmp19 = sext i32 %tmp13 to i64
+ %tmp21 = getelementptr inbounds i32, i32 addrspace(1)* %arg1, i64 %tmp19
+ store i32 %tmp17, i32 addrspace(1)* %tmp21, align 4, !tbaa !0
+ %tmp25 = add nuw nsw i32 %tmp13, 1
+ %tmp31 = icmp eq i32 %tmp25, 100
+ br i1 %tmp31, label %bb2, label %bb1
+}
+
+
attributes #0 = { "target-cpu"="fiji" }
!0 = !{!1, !1, i64 0}
diff --git a/test/CodeGen/AMDGPU/inserted-wait-states.mir b/test/CodeGen/AMDGPU/inserted-wait-states.mir
index ff9fcd1c693f..c6fe6debd225 100644
--- a/test/CodeGen/AMDGPU/inserted-wait-states.mir
+++ b/test/CodeGen/AMDGPU/inserted-wait-states.mir
@@ -246,15 +246,15 @@ body: |
S_BRANCH %bb.1
bb.1:
- FLAT_STORE_DWORDX2 %vgpr0_vgpr1, %vgpr2_vgpr3, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORDX2 %vgpr0_vgpr1, %vgpr2_vgpr3, 0, 0, 0, implicit %exec, implicit %flat_scr
%vgpr3 = V_MOV_B32_e32 0, implicit %exec
- FLAT_STORE_DWORDX3 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORDX3 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4, 0, 0, 0, implicit %exec, implicit %flat_scr
%vgpr3 = V_MOV_B32_e32 0, implicit %exec
- FLAT_STORE_DWORDX4 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORDX4 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, 0, implicit %exec, implicit %flat_scr
%vgpr3 = V_MOV_B32_e32 0, implicit %exec
- FLAT_ATOMIC_CMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, implicit %exec, implicit %flat_scr
+ FLAT_ATOMIC_CMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, implicit %exec, implicit %flat_scr
%vgpr3 = V_MOV_B32_e32 0, implicit %exec
- FLAT_ATOMIC_FCMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, implicit %exec, implicit %flat_scr
+ FLAT_ATOMIC_FCMPSWAP_X2 %vgpr0_vgpr1, %vgpr2_vgpr3_vgpr4_vgpr5, 0, 0, implicit %exec, implicit %flat_scr
%vgpr3 = V_MOV_B32_e32 0, implicit %exec
S_ENDPGM
diff --git a/test/CodeGen/AMDGPU/limit-coalesce.mir b/test/CodeGen/AMDGPU/limit-coalesce.mir
index 7d6d8a5891cd..d6b3d7b14cd2 100644
--- a/test/CodeGen/AMDGPU/limit-coalesce.mir
+++ b/test/CodeGen/AMDGPU/limit-coalesce.mir
@@ -57,15 +57,15 @@ body: |
%4.sub1 = COPY %3.sub0
undef %5.sub0 = COPY %4.sub1
%5.sub1 = COPY %4.sub0
- FLAT_STORE_DWORDX2 %vgpr0_vgpr1, killed %5, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORDX2 %vgpr0_vgpr1, killed %5, 0, 0, 0, implicit %exec, implicit %flat_scr
%6 = IMPLICIT_DEF
undef %7.sub0_sub1 = COPY %6
%7.sub2 = COPY %3.sub0
- FLAT_STORE_DWORDX3 %vgpr0_vgpr1, killed %7, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORDX3 %vgpr0_vgpr1, killed %7, 0, 0, 0, implicit %exec, implicit %flat_scr
%8 = IMPLICIT_DEF
undef %9.sub0_sub1_sub2 = COPY %8
%9.sub3 = COPY %3.sub0
- FLAT_STORE_DWORDX4 %vgpr0_vgpr1, killed %9, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORDX4 %vgpr0_vgpr1, killed %9, 0, 0, 0, implicit %exec, implicit %flat_scr
...
diff --git a/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir b/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir
index 1a0d68d81f97..31024277871d 100644
--- a/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir
+++ b/test/CodeGen/AMDGPU/rename-independent-subregs-invalid-mac-operands.mir
@@ -58,12 +58,12 @@ body: |
bb.3:
%1 = COPY killed %17
- FLAT_STORE_DWORD undef %10, %1.sub2, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORD undef %10, %1.sub2, 0, 0, 0, implicit %exec, implicit %flat_scr
%14 = COPY %1.sub1
%16 = COPY killed %1.sub0
undef %15.sub0 = COPY killed %16
%15.sub1 = COPY killed %14
- FLAT_STORE_DWORDX2 undef %11, killed %15, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORDX2 undef %11, killed %15, 0, 0, 0, implicit %exec, implicit %flat_scr
S_ENDPGM
...
diff --git a/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir b/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir
index cd0d410368c7..ba937c927c70 100644
--- a/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir
+++ b/test/CodeGen/AMDGPU/sdwa-scalar-ops.mir
@@ -214,26 +214,26 @@ body: |
%15 = S_ADDC_U32 %7.sub1, %0.sub1, implicit-def dead %scc, implicit %scc
%16 = REG_SEQUENCE %14, 1, %15, 2
%18 = COPY %16
- %17 = FLAT_LOAD_DWORD %18, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45)
+ %17 = FLAT_LOAD_DWORD %18, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45)
%60 = V_BFE_U32 %17, 8, 8, implicit %exec
%61 = V_LSHLREV_B32_e32 2, killed %60, implicit %exec
%70 = V_ADD_I32_e32 %7.sub0, %61, implicit-def %vcc, implicit %exec
%66 = COPY %13
%65 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec
%67 = REG_SEQUENCE %70, 1, killed %65, 2
- FLAT_STORE_DWORD %67, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9)
+ FLAT_STORE_DWORD %67, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9)
%37 = S_ADD_U32 %14, 4, implicit-def %scc
%38 = S_ADDC_U32 %15, 0, implicit-def dead %scc, implicit %scc
%71 = COPY killed %37
%72 = COPY killed %38
%41 = REG_SEQUENCE killed %71, 1, killed %72, 2
- %40 = FLAT_LOAD_DWORD killed %41, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep)
+ %40 = FLAT_LOAD_DWORD killed %41, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep)
%73 = V_BFE_U32 %40, 8, 8, implicit %exec
%74 = V_LSHLREV_B32_e32 2, killed %73, implicit %exec
%83 = V_ADD_I32_e32 %7.sub0, %74, implicit-def %vcc, implicit %exec
%78 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec
%80 = REG_SEQUENCE %83, 1, killed %78, 2
- FLAT_STORE_DWORD %80, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17)
+ FLAT_STORE_DWORD %80, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17)
%55 = S_ADD_U32 %0.sub0, 8, implicit-def %scc
%56 = S_ADDC_U32 %0.sub1, 0, implicit-def dead %scc, implicit %scc
%57 = REG_SEQUENCE %55, 1, killed %56, 2
@@ -377,26 +377,26 @@ body: |
%15 = S_ADDC_U32 %7.sub1, %0.sub1, implicit-def dead %scc, implicit %scc
%16 = REG_SEQUENCE %14, 1, %15, 2
%18 = COPY %16
- %17 = FLAT_LOAD_DWORD %18, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45)
+ %17 = FLAT_LOAD_DWORD %18, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.uglygep45)
%60 = V_BFE_U32 %17, 8, 8, implicit %exec
%61 = V_LSHLREV_B32_e32 %84, killed %60, implicit %exec
%70 = V_ADD_I32_e32 %7.sub0, %61, implicit-def %vcc, implicit %exec
%66 = COPY %13
%65 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec
%67 = REG_SEQUENCE %70, 1, killed %65, 2
- FLAT_STORE_DWORD %67, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9)
+ FLAT_STORE_DWORD %67, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp9)
%37 = S_ADD_U32 %14, 4, implicit-def %scc
%38 = S_ADDC_U32 %15, 0, implicit-def dead %scc, implicit %scc
%71 = COPY killed %37
%72 = COPY killed %38
%41 = REG_SEQUENCE killed %71, 1, killed %72, 2
- %40 = FLAT_LOAD_DWORD killed %41, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep)
+ %40 = FLAT_LOAD_DWORD killed %41, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.scevgep)
%73 = V_BFE_U32 %40, 8, 8, implicit %exec
%74 = V_LSHLREV_B32_e32 %84, killed %73, implicit %exec
%83 = V_ADD_I32_e32 %7.sub0, %74, implicit-def %vcc, implicit %exec
%78 = V_ADDC_U32_e32 0, %66, implicit-def %vcc, implicit %vcc, implicit %exec
%80 = REG_SEQUENCE %83, 1, killed %78, 2
- FLAT_STORE_DWORD %80, %30, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17)
+ FLAT_STORE_DWORD %80, %30, 0, 0, 0, implicit %exec, implicit %flat_scr :: (store 4 into %ir.tmp17)
%55 = S_ADD_U32 %0.sub0, 8, implicit-def %scc
%56 = S_ADDC_U32 %0.sub1, 0, implicit-def dead %scc, implicit %scc
%57 = REG_SEQUENCE %55, 1, killed %56, 2
diff --git a/test/CodeGen/AMDGPU/waitcnt.mir b/test/CodeGen/AMDGPU/waitcnt.mir
index f754415dccb4..38662e83b359 100644
--- a/test/CodeGen/AMDGPU/waitcnt.mir
+++ b/test/CodeGen/AMDGPU/waitcnt.mir
@@ -51,21 +51,21 @@ name: flat_zero_waitcnt
body: |
bb.0:
successors: %bb.1
- %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.global4)
- %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16)
+ %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.global4)
+ %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16)
%vgpr0 = V_MOV_B32_e32 %vgpr1, implicit %exec
S_BRANCH %bb.1
bb.1:
successors: %bb.2
- %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr
- %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16)
+ %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr
+ %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.global16)
%vgpr0 = V_MOV_B32_e32 %vgpr1, implicit %exec
S_BRANCH %bb.2
bb.2:
- %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.flat4)
- %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.flat16)
+ %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 4 from %ir.flat4)
+ %vgpr3_vgpr4_vgpr5_vgpr6 = FLAT_LOAD_DWORDX4 %vgpr7_vgpr8, 0, 0, 0, implicit %exec, implicit %flat_scr :: (load 16 from %ir.flat16)
%vgpr0 = V_MOV_B32_e32 %vgpr1, implicit %exec
S_ENDPGM
...
@@ -86,11 +86,11 @@ name: single_fallthrough_successor_no_end_block_wait
body: |
bb.0:
successors: %bb.1
- %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr
+ %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr
bb.1:
%vgpr3_vgpr4 = V_LSHLREV_B64 4, %vgpr7_vgpr8, implicit %exec
- FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, 0, implicit %exec, implicit %flat_scr
S_ENDPGM
...
---
@@ -114,15 +114,15 @@ name: single_branch_successor_not_next_block
body: |
bb.0:
successors: %bb.2
- %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, implicit %exec, implicit %flat_scr
+ %vgpr0 = FLAT_LOAD_DWORD %vgpr1_vgpr2, 0, 0, 0, implicit %exec, implicit %flat_scr
S_BRANCH %bb.2
bb.1:
- FLAT_STORE_DWORD %vgpr8_vgpr9, %vgpr10, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORD %vgpr8_vgpr9, %vgpr10, 0, 0, 0, implicit %exec, implicit %flat_scr
S_ENDPGM
bb.2:
%vgpr3_vgpr4 = V_LSHLREV_B64 4, %vgpr7_vgpr8, implicit %exec
- FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, implicit %exec, implicit %flat_scr
+ FLAT_STORE_DWORD %vgpr3_vgpr4, %vgpr0, 0, 0, 0, implicit %exec, implicit %flat_scr
S_ENDPGM
...
diff --git a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll
index 05902c22fb98..6663a9210b87 100644
--- a/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll
+++ b/test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll
@@ -621,28 +621,18 @@ define arm_aapcscc [3 x i32] @test_tiny_int_arrays([2 x i32] %arr) {
; CHECK: liveins: %r0, %r1
; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0
; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1
-; CHECK: [[ARG_ARR0:%[0-9]+]](s64) = IMPLICIT_DEF
-; CHECK: [[ARG_ARR1:%[0-9]+]](s64) = G_INSERT [[ARG_ARR0]], [[R0]](s32), 0
-; CHECK: [[ARG_ARR2:%[0-9]+]](s64) = G_INSERT [[ARG_ARR1]], [[R1]](s32), 32
-; CHECK: [[ARG_ARR:%[0-9]+]](s64) = COPY [[ARG_ARR2]]
+; CHECK: [[ARG_ARR:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32)
; CHECK: ADJCALLSTACKDOWN 0, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s64), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s64), 32
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR]](s64)
; CHECK: %r0 = COPY [[R0]]
; CHECK: %r1 = COPY [[R1]]
; CHECK: BLX @tiny_int_arrays_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1
; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0
; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1
; CHECK: [[R2:%[0-9]+]](s32) = COPY %r2
-; CHECK: [[RES_ARR0:%[0-9]+]](s96) = IMPLICIT_DEF
-; CHECK: [[RES_ARR1:%[0-9]+]](s96) = G_INSERT [[RES_ARR0]], [[R0]](s32), 0
-; CHECK: [[RES_ARR2:%[0-9]+]](s96) = G_INSERT [[RES_ARR1]], [[R1]](s32), 32
-; CHECK: [[RES_ARR3:%[0-9]+]](s96) = G_INSERT [[RES_ARR2]], [[R2]](s32), 64
-; CHECK: [[RES_ARR:%[0-9]+]](s96) = COPY [[RES_ARR3]]
+; CHECK: [[RES_ARR:%[0-9]+]](s96) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32)
; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s96), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s96), 32
-; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s96), 64
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32) = G_UNMERGE_VALUES [[RES_ARR]](s96)
; FIXME: This doesn't seem correct with regard to the AAPCS docs (which say
; that composite types larger than 4 bytes should be passed through memory),
; but it's what DAGISel does. We should fix it in the common code for both.
@@ -664,19 +654,11 @@ define arm_aapcscc void @test_multiple_int_arrays([2 x i32] %arr0, [2 x i32] %ar
; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1
; CHECK: [[R2:%[0-9]+]](s32) = COPY %r2
; CHECK: [[R3:%[0-9]+]](s32) = COPY %r3
-; CHECK: [[ARG_ARR0_0:%[0-9]+]](s64) = IMPLICIT_DEF
-; CHECK: [[ARG_ARR0_1:%[0-9]+]](s64) = G_INSERT [[ARG_ARR0_0]], [[R0]](s32), 0
-; CHECK: [[ARG_ARR0_2:%[0-9]+]](s64) = G_INSERT [[ARG_ARR0_1]], [[R1]](s32), 32
-; CHECK: [[ARG_ARR0:%[0-9]+]](s64) = COPY [[ARG_ARR0_2]]
-; CHECK: [[ARG_ARR1_0:%[0-9]+]](s64) = IMPLICIT_DEF
-; CHECK: [[ARG_ARR1_1:%[0-9]+]](s64) = G_INSERT [[ARG_ARR1_0]], [[R2]](s32), 0
-; CHECK: [[ARG_ARR1_2:%[0-9]+]](s64) = G_INSERT [[ARG_ARR1_1]], [[R3]](s32), 32
-; CHECK: [[ARG_ARR1:%[0-9]+]](s64) = COPY [[ARG_ARR1_2]]
+; CHECK: [[ARG_ARR0:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32)
+; CHECK: [[ARG_ARR1:%[0-9]+]](s64) = G_MERGE_VALUES [[R2]](s32), [[R3]](s32)
; CHECK: ADJCALLSTACKDOWN 0, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR0]](s64), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR0]](s64), 32
-; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR1]](s64), 0
-; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR1]](s64), 32
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR0]](s64)
+; CHECK: [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR1]](s64)
; CHECK: %r0 = COPY [[R0]]
; CHECK: %r1 = COPY [[R1]]
; CHECK: %r2 = COPY [[R2]]
@@ -707,21 +689,9 @@ define arm_aapcscc void @test_large_int_arrays([20 x i32] %arr) {
; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]]
-; CHECK: [[ARG_ARR0:%[0-9]+]](s640) = IMPLICIT_DEF
-; CHECK: [[ARG_ARR1:%[0-9]+]](s640) = G_INSERT [[ARG_ARR0]], [[R0]](s32), 0
-; CHECK: [[ARG_ARR2:%[0-9]+]](s640) = G_INSERT [[ARG_ARR1]], [[R1]](s32), 32
-; CHECK: [[ARG_ARR3:%[0-9]+]](s640) = G_INSERT [[ARG_ARR2]], [[R2]](s32), 64
-; CHECK: [[ARG_ARR4:%[0-9]+]](s640) = G_INSERT [[ARG_ARR3]], [[R3]](s32), 96
-; CHECK: [[ARG_ARR5:%[0-9]+]](s640) = G_INSERT [[ARG_ARR4]], [[FIRST_STACK_ELEMENT]](s32), 128
-; CHECK: [[ARG_ARR6:%[0-9]+]](s640) = G_INSERT {{%[0-9]+}}, [[LAST_STACK_ELEMENT]](s32), 608
-; CHECK: [[ARG_ARR:%[0-9]+]](s640) = COPY [[ARG_ARR6]]
+; CHECK: [[ARG_ARR:%[0-9]+]](s640) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32), [[R3]](s32), [[FIRST_STACK_ELEMENT]](s32), {{.*}}, [[LAST_STACK_ELEMENT]](s32)
; CHECK: ADJCALLSTACKDOWN 64, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 32
-; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 64
-; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 96
-; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 128
-; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s640), 608
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32), [[FIRST_STACK_ELEMENT:%[0-9]+]](s32), {{.*}}, [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR]](s640)
; CHECK: %r0 = COPY [[R0]]
; CHECK: %r1 = COPY [[R1]]
; CHECK: %r2 = COPY [[R2]]
@@ -761,15 +731,9 @@ define arm_aapcscc [2 x float] @test_fp_arrays_aapcs([3 x double] %arr) {
; BIG: [[ARR1:%[0-9]+]](s64) = G_MERGE_VALUES [[ARR1_1]](s32), [[ARR1_0]](s32)
; CHECK: [[ARR2_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[ARR2_ID]]
; CHECK: [[ARR2:%[0-9]+]](s64) = G_LOAD [[ARR2_FI]]{{.*}}load 8 from %fixed-stack.[[ARR2_ID]]
-; CHECK: [[ARR_MERGED_0:%[0-9]+]](s192) = IMPLICIT_DEF
-; CHECK: [[ARR_MERGED_1:%[0-9]+]](s192) = G_INSERT [[ARR_MERGED_0]], [[ARR0]](s64), 0
-; CHECK: [[ARR_MERGED_2:%[0-9]+]](s192) = G_INSERT [[ARR_MERGED_1]], [[ARR1]](s64), 64
-; CHECK: [[ARR_MERGED_3:%[0-9]+]](s192) = G_INSERT [[ARR_MERGED_2]], [[ARR2]](s64), 128
-; CHECK: [[ARR_MERGED:%[0-9]+]](s192) = COPY [[ARR_MERGED_3]]
+; CHECK: [[ARR_MERGED:%[0-9]+]](s192) = G_MERGE_VALUES [[ARR0]](s64), [[ARR1]](s64), [[ARR2]](s64)
; CHECK: ADJCALLSTACKDOWN 8, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[ARR0:%[0-9]+]](s64) = G_EXTRACT [[ARR_MERGED]](s192), 0
-; CHECK: [[ARR1:%[0-9]+]](s64) = G_EXTRACT [[ARR_MERGED]](s192), 64
-; CHECK: [[ARR2:%[0-9]+]](s64) = G_EXTRACT [[ARR_MERGED]](s192), 128
+; CHECK: [[ARR0:%[0-9]+]](s64), [[ARR1:%[0-9]+]](s64), [[ARR2:%[0-9]+]](s64) = G_UNMERGE_VALUES [[ARR_MERGED]](s192)
; CHECK: [[ARR0_0:%[0-9]+]](s32), [[ARR0_1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARR0]](s64)
; LITTLE: %r0 = COPY [[ARR0_0]](s32)
; LITTLE: %r1 = COPY [[ARR0_1]](s32)
@@ -787,13 +751,9 @@ define arm_aapcscc [2 x float] @test_fp_arrays_aapcs([3 x double] %arr) {
; CHECK: BLX @fp_arrays_aapcs_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1
; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0
; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1
-; CHECK: [[R_MERGED_0:%[0-9]+]](s64) = IMPLICIT_DEF
-; CHECK: [[R_MERGED_1:%[0-9]+]](s64) = G_INSERT [[R_MERGED_0]], [[R0]](s32), 0
-; CHECK: [[R_MERGED_2:%[0-9]+]](s64) = G_INSERT [[R_MERGED_1]], [[R1]](s32), 32
-; CHECK: [[R_MERGED:%[0-9]+]](s64) = COPY [[R_MERGED_2]]
+; CHECK: [[R_MERGED:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32)
; CHECK: ADJCALLSTACKUP 8, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s64), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s64), 32
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[R_MERGED]](s64)
; CHECK: %r0 = COPY [[R0]]
; CHECK: %r1 = COPY [[R1]]
; CHECK: BX_RET 14, _, implicit %r0, implicit %r1
@@ -826,33 +786,13 @@ define arm_aapcs_vfpcc [4 x float] @test_fp_arrays_aapcs_vfp([3 x double] %x, [3
; CHECK: [[Z2:%[0-9]+]](s64) = G_LOAD [[Z2_FI]]{{.*}}load 8
; CHECK: [[Z3_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[Z3_ID]]
; CHECK: [[Z3:%[0-9]+]](s64) = G_LOAD [[Z3_FI]]{{.*}}load 8
-; CHECK: [[X_ARR_0:%[0-9]+]](s192) = IMPLICIT_DEF
-; CHECK: [[X_ARR_1:%[0-9]+]](s192) = G_INSERT [[X_ARR_0]], [[X0]](s64), 0
-; CHECK: [[X_ARR_2:%[0-9]+]](s192) = G_INSERT [[X_ARR_1]], [[X1]](s64), 64
-; CHECK: [[X_ARR_3:%[0-9]+]](s192) = G_INSERT [[X_ARR_2]], [[X2]](s64), 128
-; CHECK: [[X_ARR:%[0-9]+]](s192) = COPY [[X_ARR_3]](s192)
-; CHECK: [[Y_ARR_0:%[0-9]+]](s96) = IMPLICIT_DEF
-; CHECK: [[Y_ARR_1:%[0-9]+]](s96) = G_INSERT [[Y_ARR_0]], [[Y0]](s32), 0
-; CHECK: [[Y_ARR_2:%[0-9]+]](s96) = G_INSERT [[Y_ARR_1]], [[Y1]](s32), 32
-; CHECK: [[Y_ARR_3:%[0-9]+]](s96) = G_INSERT [[Y_ARR_2]], [[Y2]](s32), 64
-; CHECK: [[Y_ARR:%[0-9]+]](s96) = COPY [[Y_ARR_3]](s96)
-; CHECK: [[Z_ARR_0:%[0-9]+]](s256) = IMPLICIT_DEF
-; CHECK: [[Z_ARR_1:%[0-9]+]](s256) = G_INSERT [[Z_ARR_0]], [[Z0]](s64), 0
-; CHECK: [[Z_ARR_2:%[0-9]+]](s256) = G_INSERT [[Z_ARR_1]], [[Z1]](s64), 64
-; CHECK: [[Z_ARR_3:%[0-9]+]](s256) = G_INSERT [[Z_ARR_2]], [[Z2]](s64), 128
-; CHECK: [[Z_ARR_4:%[0-9]+]](s256) = G_INSERT [[Z_ARR_3]], [[Z3]](s64), 192
-; CHECK: [[Z_ARR:%[0-9]+]](s256) = COPY [[Z_ARR_4]](s256)
+; CHECK: [[X_ARR:%[0-9]+]](s192) = G_MERGE_VALUES [[X0]](s64), [[X1]](s64), [[X2]](s64)
+; CHECK: [[Y_ARR:%[0-9]+]](s96) = G_MERGE_VALUES [[Y0]](s32), [[Y1]](s32), [[Y2]](s32)
+; CHECK: [[Z_ARR:%[0-9]+]](s256) = G_MERGE_VALUES [[Z0]](s64), [[Z1]](s64), [[Z2]](s64), [[Z3]](s64)
; CHECK: ADJCALLSTACKDOWN 32, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[X0:%[0-9]+]](s64) = G_EXTRACT [[X_ARR]](s192), 0
-; CHECK: [[X1:%[0-9]+]](s64) = G_EXTRACT [[X_ARR]](s192), 64
-; CHECK: [[X2:%[0-9]+]](s64) = G_EXTRACT [[X_ARR]](s192), 128
-; CHECK: [[Y0:%[0-9]+]](s32) = G_EXTRACT [[Y_ARR]](s96), 0
-; CHECK: [[Y1:%[0-9]+]](s32) = G_EXTRACT [[Y_ARR]](s96), 32
-; CHECK: [[Y2:%[0-9]+]](s32) = G_EXTRACT [[Y_ARR]](s96), 64
-; CHECK: [[Z0:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 0
-; CHECK: [[Z1:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 64
-; CHECK: [[Z2:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 128
-; CHECK: [[Z3:%[0-9]+]](s64) = G_EXTRACT [[Z_ARR]](s256), 192
+; CHECK: [[X0:%[0-9]+]](s64), [[X1:%[0-9]+]](s64), [[X2:%[0-9]+]](s64) = G_UNMERGE_VALUES [[X_ARR]](s192)
+; CHECK: [[Y0:%[0-9]+]](s32), [[Y1:%[0-9]+]](s32), [[Y2:%[0-9]+]](s32) = G_UNMERGE_VALUES [[Y_ARR]](s96)
+; CHECK: [[Z0:%[0-9]+]](s64), [[Z1:%[0-9]+]](s64), [[Z2:%[0-9]+]](s64), [[Z3:%[0-9]+]](s64) = G_UNMERGE_VALUES [[Z_ARR]](s256)
; CHECK: %d0 = COPY [[X0]](s64)
; CHECK: %d1 = COPY [[X1]](s64)
; CHECK: %d2 = COPY [[X2]](s64)
@@ -880,17 +820,9 @@ define arm_aapcs_vfpcc [4 x float] @test_fp_arrays_aapcs_vfp([3 x double] %x, [3
; CHECK: [[R1:%[0-9]+]](s32) = COPY %s1
; CHECK: [[R2:%[0-9]+]](s32) = COPY %s2
; CHECK: [[R3:%[0-9]+]](s32) = COPY %s3
-; CHECK: [[R_MERGED_0:%[0-9]+]](s128) = IMPLICIT_DEF
-; CHECK: [[R_MERGED_1:%[0-9]+]](s128) = G_INSERT [[R_MERGED_0]], [[R0]](s32), 0
-; CHECK: [[R_MERGED_2:%[0-9]+]](s128) = G_INSERT [[R_MERGED_1]], [[R1]](s32), 32
-; CHECK: [[R_MERGED_3:%[0-9]+]](s128) = G_INSERT [[R_MERGED_2]], [[R2]](s32), 64
-; CHECK: [[R_MERGED_4:%[0-9]+]](s128) = G_INSERT [[R_MERGED_3]], [[R3]](s32), 96
-; CHECK: [[R_MERGED:%[0-9]+]](s128) = COPY [[R_MERGED_4]]
+; CHECK: [[R_MERGED:%[0-9]+]](s128) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32), [[R3]](s32)
; CHECK: ADJCALLSTACKUP 32, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 32
-; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 64
-; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[R_MERGED]](s128), 96
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32) = G_UNMERGE_VALUES [[R_MERGED]](s128)
; CHECK: %s0 = COPY [[R0]]
; CHECK: %s1 = COPY [[R1]]
; CHECK: %s2 = COPY [[R2]]
@@ -919,21 +851,9 @@ define arm_aapcscc [2 x i32*] @test_tough_arrays([6 x [4 x i32]] %arr) {
; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[FIRST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]]
; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load 4 from %fixed-stack.[[LAST_STACK_ID]]
-; CHECK: [[ARG_ARR0:%[0-9]+]](s768) = IMPLICIT_DEF
-; CHECK: [[ARG_ARR1:%[0-9]+]](s768) = G_INSERT [[ARG_ARR0]], [[R0]](s32), 0
-; CHECK: [[ARG_ARR2:%[0-9]+]](s768) = G_INSERT [[ARG_ARR1]], [[R1]](s32), 32
-; CHECK: [[ARG_ARR3:%[0-9]+]](s768) = G_INSERT [[ARG_ARR2]], [[R2]](s32), 64
-; CHECK: [[ARG_ARR4:%[0-9]+]](s768) = G_INSERT [[ARG_ARR3]], [[R3]](s32), 96
-; CHECK: [[ARG_ARR5:%[0-9]+]](s768) = G_INSERT [[ARG_ARR4]], [[FIRST_STACK_ELEMENT]](s32), 128
-; CHECK: [[ARG_ARR6:%[0-9]+]](s768) = G_INSERT {{%[0-9]+}}, [[LAST_STACK_ELEMENT]](s32), 736
-; CHECK: [[ARG_ARR:%[0-9]+]](s768) = COPY [[ARG_ARR6]]
+; CHECK: [[ARG_ARR:%[0-9]+]](s768) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32), [[R2]](s32), [[R3]](s32), [[FIRST_STACK_ELEMENT]](s32), {{.*}}, [[LAST_STACK_ELEMENT]](s32)
; CHECK: ADJCALLSTACKDOWN 80, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 32
-; CHECK: [[R2:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 64
-; CHECK: [[R3:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 96
-; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 128
-; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_EXTRACT [[ARG_ARR]](s768), 736
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32), [[R2:%[0-9]+]](s32), [[R3:%[0-9]+]](s32), [[FIRST_STACK_ELEMENT:%[0-9]+]](s32), {{.*}}, [[LAST_STACK_ELEMENT:%[0-9]+]](s32) = G_UNMERGE_VALUES [[ARG_ARR]](s768)
; CHECK: %r0 = COPY [[R0]]
; CHECK: %r1 = COPY [[R1]]
; CHECK: %r2 = COPY [[R2]]
@@ -951,13 +871,9 @@ define arm_aapcscc [2 x i32*] @test_tough_arrays([6 x [4 x i32]] %arr) {
; CHECK: BLX @tough_arrays_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1
; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0
; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1
-; CHECK: [[RES_ARR0:%[0-9]+]](s64) = IMPLICIT_DEF
-; CHECK: [[RES_ARR1:%[0-9]+]](s64) = G_INSERT [[RES_ARR0]], [[R0]](s32), 0
-; CHECK: [[RES_ARR2:%[0-9]+]](s64) = G_INSERT [[RES_ARR1]], [[R1]](s32), 32
-; CHECK: [[RES_ARR:%[0-9]+]](s64) = COPY [[RES_ARR2]]
+; CHECK: [[RES_ARR:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32)
; CHECK: ADJCALLSTACKUP 80, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s64), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[RES_ARR]](s64), 32
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[RES_ARR]](s64)
; CHECK: %r0 = COPY [[R0]]
; CHECK: %r1 = COPY [[R1]]
; CHECK: BX_RET 14, _, implicit %r0, implicit %r1
@@ -966,65 +882,28 @@ entry:
ret [2 x i32*] %r
}
-declare arm_aapcscc {i32, i32} @structs_target({i32, i32}, {i32*, float, i32, double})
+declare arm_aapcscc {i32, i32} @structs_target({i32, i32})
-define arm_aapcscc {i32, i32} @test_structs({i32, i32} %x, {i32*, float, i32, double} %y) {
+define arm_aapcscc {i32, i32} @test_structs({i32, i32} %x) {
; CHECK-LABEL: test_structs
-; CHECK: fixedStack:
-; CHECK-DAG: id: [[Y2_ID:[0-9]+]], type: default, offset: 0, size: 4,
-; CHECK-DAG: id: [[Y3_ID:[0-9]+]], type: default, offset: 8, size: 8,
-; CHECK: liveins: %r0, %r1, %r2, %r3
+; CHECK: liveins: %r0, %r1
; CHECK-DAG: [[X0:%[0-9]+]](s32) = COPY %r0
; CHECK-DAG: [[X1:%[0-9]+]](s32) = COPY %r1
-; CHECK-DAG: [[Y0:%[0-9]+]](s32) = COPY %r2
-; CHECK-DAG: [[Y1:%[0-9]+]](s32) = COPY %r3
-; CHECK: [[Y2_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[Y2_ID]]
-; CHECK: [[Y2:%[0-9]+]](s32) = G_LOAD [[Y2_ADDR]](p0){{.*}}load 4
-; CHECK: [[Y3_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[Y3_ID]]
-; CHECK: [[Y3:%[0-9]+]](s64) = G_LOAD [[Y3_ADDR]](p0){{.*}}load 8
-; CHECK: [[X_0:%[0-9]+]](s64) = IMPLICIT_DEF
-; CHECK: [[X_1:%[0-9]+]](s64) = G_INSERT [[X_0]], [[X0]](s32), 0
-; CHECK: [[X_2:%[0-9]+]](s64) = G_INSERT [[X_1]], [[X1]](s32), 32
-; CHECK: [[X:%[0-9]+]](s64) = COPY [[X_2]]
-; CHECK: [[Y_0:%[0-9]+]](s192) = IMPLICIT_DEF
-; CHECK: [[Y_1:%[0-9]+]](s192) = G_INSERT [[Y_0]], [[Y0]](s32), 0
-; CHECK: [[Y_2:%[0-9]+]](s192) = G_INSERT [[Y_1]], [[Y1]](s32), 32
-; CHECK: [[Y_3:%[0-9]+]](s192) = G_INSERT [[Y_2]], [[Y2]](s32), 64
-; CHECK: [[Y_4:%[0-9]+]](s192) = G_INSERT [[Y_3]], [[Y3]](s64), 128
-; CHECK: [[Y:%[0-9]+]](s192) = COPY [[Y_4]]
-; CHECK: ADJCALLSTACKDOWN 16, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[X0:%[0-9]+]](s32) = G_EXTRACT [[X]](s64), 0
-; CHECK: [[X1:%[0-9]+]](s32) = G_EXTRACT [[X]](s64), 32
-; CHECK: [[Y0:%[0-9]+]](s32) = G_EXTRACT [[Y]](s192), 0
-; CHECK: [[Y1:%[0-9]+]](s32) = G_EXTRACT [[Y]](s192), 32
-; CHECK: [[Y2:%[0-9]+]](s32) = G_EXTRACT [[Y]](s192), 64
-; CHECK: [[Y3:%[0-9]+]](s64) = G_EXTRACT [[Y]](s192), 128
+; CHECK: [[X:%[0-9]+]](s64) = G_MERGE_VALUES [[X0]](s32), [[X1]](s32)
+; CHECK: ADJCALLSTACKDOWN 0, 0, 14, _, implicit-def %sp, implicit %sp
+; CHECK: [[X0:%[0-9]+]](s32), [[X1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[X]](s64)
; CHECK-DAG: %r0 = COPY [[X0]](s32)
; CHECK-DAG: %r1 = COPY [[X1]](s32)
-; CHECK-DAG: %r2 = COPY [[Y0]](s32)
-; CHECK-DAG: %r3 = COPY [[Y1]](s32)
-; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
-; CHECK: [[Y2_OFF:%[0-9]+]](s32) = G_CONSTANT i32 0
-; CHECK: [[Y2_ADDR:%[0-9]+]](p0) = G_GEP [[SP]], [[Y2_OFF]](s32)
-; CHECK: G_STORE [[Y2]](s32), [[Y2_ADDR]](p0){{.*}}store 4
-; CHECK: [[SP:%[0-9]+]](p0) = COPY %sp
-; CHECK: [[Y3_OFF:%[0-9]+]](s32) = G_CONSTANT i32 8
-; CHECK: [[Y3_ADDR:%[0-9]+]](p0) = G_GEP [[SP]], [[Y3_OFF]](s32)
-; CHECK: G_STORE [[Y3]](s64), [[Y3_ADDR]](p0){{.*}}store 8
-; CHECK: BLX @structs_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0, implicit-def %r1
+; CHECK: BLX @structs_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1
; CHECK: [[R0:%[0-9]+]](s32) = COPY %r0
; CHECK: [[R1:%[0-9]+]](s32) = COPY %r1
-; CHECK: [[R_0:%[0-9]+]](s64) = IMPLICIT_DEF
-; CHECK: [[R_1:%[0-9]+]](s64) = G_INSERT [[R_0]], [[R0]](s32), 0
-; CHECK: [[R_2:%[0-9]+]](s64) = G_INSERT [[R_1]], [[R1]](s32), 32
-; CHECK: [[R:%[0-9]+]](s64) = COPY [[R_2]]
-; CHECK: ADJCALLSTACKUP 16, 0, 14, _, implicit-def %sp, implicit %sp
-; CHECK: [[R0:%[0-9]+]](s32) = G_EXTRACT [[R]](s64), 0
-; CHECK: [[R1:%[0-9]+]](s32) = G_EXTRACT [[R]](s64), 32
+; CHECK: [[R:%[0-9]+]](s64) = G_MERGE_VALUES [[R0]](s32), [[R1]](s32)
+; CHECK: ADJCALLSTACKUP 0, 0, 14, _, implicit-def %sp, implicit %sp
+; CHECK: [[R0:%[0-9]+]](s32), [[R1:%[0-9]+]](s32) = G_UNMERGE_VALUES [[R]](s64)
; CHECK: %r0 = COPY [[R0]](s32)
; CHECK: %r1 = COPY [[R1]](s32)
; CHECK: BX_RET 14, _, implicit %r0, implicit %r1
- %r = notail call arm_aapcscc {i32, i32} @structs_target({i32, i32} %x, {i32*, float, i32, double} %y)
+ %r = notail call arm_aapcscc {i32, i32} @structs_target({i32, i32} %x)
ret {i32, i32} %r
}
diff --git a/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll b/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll
index 2881740b016f..c778caacd0f4 100644
--- a/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll
+++ b/test/CodeGen/ARM/GlobalISel/arm-isel-divmod.ll
@@ -66,3 +66,24 @@ define arm_aapcscc i8 @test_udiv_i8(i8 %a, i8 %b) {
ret i8 %r
}
+define arm_aapcscc i32 @test_srem_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: test_srem_i32:
+; HWDIV: sdiv [[Q:r[0-9]+]], r0, r1
+; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
+; HWDIV: sub r0, r0, [[P]]
+; SOFT-AEABI: blx __aeabi_idivmod
+; SOFT-DEFAULT: blx __modsi3
+ %r = srem i32 %x, %y
+ ret i32 %r
+}
+
+define arm_aapcscc i32 @test_urem_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: test_urem_i32:
+; HWDIV: udiv [[Q:r[0-9]+]], r0, r1
+; HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
+; HWDIV: sub r0, r0, [[P]]
+; SOFT-AEABI: blx __aeabi_uidivmod
+; SOFT-DEFAULT: blx __umodsi3
+ %r = urem i32 %x, %y
+ ret i32 %r
+}
diff --git a/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir b/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir
index 6f3e09d328cf..c93e7fa0ec56 100644
--- a/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir
+++ b/test/CodeGen/ARM/GlobalISel/arm-legalize-divmod.mir
@@ -11,6 +11,9 @@
define void @test_sdiv_i8() { ret void }
define void @test_udiv_i8() { ret void }
+
+ define void @test_srem_i32() { ret void }
+ define void @test_urem_i32() { ret void }
...
---
name: test_sdiv_i32
@@ -228,3 +231,75 @@ body: |
%r0 = COPY %2(s8)
BX_RET 14, _, implicit %r0
...
+---
+name: test_srem_i32
+# CHECK-LABEL: name: test_srem_i32
+legalized: false
+# CHECK: legalized: true
+regBankSelected: false
+selected: false
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: _ }
+ - { id: 1, class: _ }
+ - { id: 2, class: _ }
+body: |
+ bb.0:
+ liveins: %r0, %r1
+
+ ; CHECK-DAG: [[X:%[0-9]+]](s32) = COPY %r0
+ ; CHECK-DAG: [[Y:%[0-9]+]](s32) = COPY %r1
+ %0(s32) = COPY %r0
+ %1(s32) = COPY %r1
+ ; HWDIV: [[Q:%[0-9]+]](s32) = G_SDIV [[X]], [[Y]]
+ ; HWDIV: [[P:%[0-9]+]](s32) = G_MUL [[Q]], [[Y]]
+ ; HWDIV: [[R:%[0-9]+]](s32) = G_SUB [[X]], [[P]]
+ ; SOFT: ADJCALLSTACKDOWN
+ ; SOFT-DAG: %r0 = COPY [[X]]
+ ; SOFT-DAG: %r1 = COPY [[Y]]
+ ; SOFT-AEABI: BLX $__aeabi_idivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1
+ ; SOFT-AEABI: [[R:%[0-9]+]](s32) = COPY %r1
+ ; SOFT-DEFAULT: BLX $__modsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+ ; SOFT-DEFAULT: [[R:%[0-9]+]](s32) = COPY %r0
+ ; SOFT: ADJCALLSTACKUP
+ %2(s32) = G_SREM %0, %1
+ ; CHECK: %r0 = COPY [[R]]
+ %r0 = COPY %2(s32)
+ BX_RET 14, _, implicit %r0
+...
+---
+name: test_urem_i32
+# CHECK-LABEL: name: test_urem_i32
+legalized: false
+# CHECK: legalized: true
+regBankSelected: false
+selected: false
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: _ }
+ - { id: 1, class: _ }
+ - { id: 2, class: _ }
+body: |
+ bb.0:
+ liveins: %r0, %r1
+
+ ; CHECK-DAG: [[X:%[0-9]+]](s32) = COPY %r0
+ ; CHECK-DAG: [[Y:%[0-9]+]](s32) = COPY %r1
+ %0(s32) = COPY %r0
+ %1(s32) = COPY %r1
+ ; HWDIV: [[Q:%[0-9]+]](s32) = G_UDIV [[X]], [[Y]]
+ ; HWDIV: [[P:%[0-9]+]](s32) = G_MUL [[Q]], [[Y]]
+ ; HWDIV: [[R:%[0-9]+]](s32) = G_SUB [[X]], [[P]]
+ ; SOFT: ADJCALLSTACKDOWN
+ ; SOFT-DAG: %r0 = COPY [[X]]
+ ; SOFT-DAG: %r1 = COPY [[Y]]
+ ; SOFT-AEABI: BLX $__aeabi_uidivmod, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0, implicit-def %r1
+ ; SOFT-AEABI: [[R:%[0-9]+]](s32) = COPY %r1
+ ; SOFT-DEFAULT: BLX $__umodsi3, {{.*}}, implicit %r0, implicit %r1, implicit-def %r0
+ ; SOFT-DEFAULT: [[R:%[0-9]+]](s32) = COPY %r0
+ ; SOFT: ADJCALLSTACKUP
+ %2(s32) = G_UREM %0, %1
+ ; CHECK: %r0 = COPY [[R]]
+ %r0 = COPY %2(s32)
+ BX_RET 14, _, implicit %r0
+...
diff --git a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll
index 34f00aebe1be..f2f9c5d2a81d 100644
--- a/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll
+++ b/test/CodeGen/ARM/GlobalISel/arm-unsupported.ll
@@ -65,6 +65,14 @@ define %large.struct @test_large_struct_return() {
ret %large.struct %r
}
+%mixed.struct = type {i32*, float, i32}
+
+define %mixed.struct @test_mixed_struct(%mixed.struct %x) {
+; CHECK: remark: {{.*}} unable to lower arguments: %mixed.struct (%mixed.struct)*
+; CHECK-LABEL: warning: Instruction selection used fallback path for test_mixed_struct
+ ret %mixed.struct %x
+}
+
define void @test_vararg_definition(i32 %a, ...) {
; CHECK: remark: {{.*}} unable to lower arguments: void (i32, ...)*
; CHECK-LABEL: warning: Instruction selection used fallback path for test_vararg_definition
diff --git a/test/CodeGen/ARM/cortex-a57-misched-vfma.ll b/test/CodeGen/ARM/cortex-a57-misched-vfma.ll
index 5f914323861a..e234e179ed07 100644
--- a/test/CodeGen/ARM/cortex-a57-misched-vfma.ll
+++ b/test/CodeGen/ARM/cortex-a57-misched-vfma.ll
@@ -156,3 +156,41 @@ define <2 x float> @Test4(<2 x float> %f1, <2 x float> %f2, <2 x float> %f3, <2
%sub2 = fsub <2 x float> %sub1, %mul3
ret <2 x float> %sub2
}
+
+define float @Test5(float %f1, float %f2, float %f3) {
+; CHECK: ********** MI Scheduling **********
+; CHECK: Test5:BB#0
+
+; CHECK-DEFAULT: VNMLS
+; CHECK-FAST: VFNMS
+; CHECK: Latency : 9
+; CHECK: Successors:
+; CHECK: data
+; > VMLAS not-optimized latency to VMOVRS = 9
+; CHECK-SAME: Latency=9
+
+; f1 * f2 - f3 ==> VNMLS/VFNMS
+ %mul = fmul float %f1, %f2
+ %sub = fsub float %mul, %f3
+ ret float %sub
+}
+
+
+define float @Test6(float %f1, float %f2, float %f3) {
+; CHECK: ********** MI Scheduling **********
+; CHECK: Test6:BB#0
+
+; CHECK-DEFAULT: VNMLA
+; CHECK-FAST: VFNMA
+; CHECK: Latency : 9
+; CHECK: Successors:
+; CHECK: data
+; > VMLAS not-optimized latency to VMOVRS = 9
+; CHECK-SAME: Latency=9
+
+; f1 * f2 - f3 ==> VNMLA/VFNMA
+ %mul = fmul float %f1, %f2
+ %sub1 = fsub float -0.0, %mul
+ %sub2 = fsub float %sub1, %f2
+ ret float %sub2
+}
diff --git a/test/CodeGen/ARM/debug-info-blocks.ll b/test/CodeGen/ARM/debug-info-blocks.ll
index 1e9d890e9333..6019a9410b03 100644
--- a/test/CodeGen/ARM/debug-info-blocks.ll
+++ b/test/CodeGen/ARM/debug-info-blocks.ll
@@ -273,6 +273,6 @@ define hidden void @foobar_func_block_invoke_0(i8* %.block_descriptor, %0* %load
!160 = !DIFile(filename: "header.h", directory: "/Volumes/Sandbox/llvm")
!161 = !{!"header2.h", !"/Volumes/Sandbox/llvm"}
!162 = !{i32 1, !"Debug Info Version", i32 3}
-!163 = !DIExpression(DW_OP_plus, 20, DW_OP_deref, DW_OP_plus, 4, DW_OP_deref, DW_OP_plus, 24)
-!164 = !DIExpression(DW_OP_deref, DW_OP_plus, 24)
-!165 = !DIExpression(DW_OP_deref, DW_OP_plus, 28)
+!163 = !DIExpression(DW_OP_plus_uconst, 20, DW_OP_deref, DW_OP_plus_uconst, 4, DW_OP_deref, DW_OP_plus_uconst, 24)
+!164 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 24)
+!165 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 28)
diff --git a/test/CodeGen/ARM/sincos.ll b/test/CodeGen/ARM/sincos.ll
index 5be0044ddbd3..42a834d24b3e 100644
--- a/test/CodeGen/ARM/sincos.ll
+++ b/test/CodeGen/ARM/sincos.ll
@@ -1,10 +1,12 @@
; RUN: llc < %s -mtriple=armv7-apple-ios6 -mcpu=cortex-a8 | FileCheck %s --check-prefix=NOOPT
; RUN: llc < %s -mtriple=armv7-apple-ios7 -mcpu=cortex-a8 | FileCheck %s --check-prefix=SINCOS
-; RUN: llc < %s -mtriple=armv7-linux-gnu -mcpu=cortex-a8 | FileCheck %s --check-prefix=NOOPT-GNU
+; RUN: llc < %s -mtriple=armv7-linux-gnu -mcpu=cortex-a8 | FileCheck %s --check-prefix=SINCOS-GNU
; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a8 \
; RUN: --enable-unsafe-fp-math | FileCheck %s --check-prefix=SINCOS-GNU
-; Combine sin / cos into a single call.
+; Combine sin / cos into a single call unless they may write errno (as
+; captured by readnone attrbiute, controlled by clang -fmath-errno
+; setting).
; rdar://12856873
define float @test1(float %x) nounwind {
@@ -19,12 +21,28 @@ entry:
; NOOPT: bl _sinf
; NOOPT: bl _cosf
-; NOOPT-GNU-LABEL: test1:
-; NOOPT-GNU: bl sinf
-; NOOPT-GNU: bl cosf
+ %call = tail call float @sinf(float %x) readnone
+ %call1 = tail call float @cosf(float %x) readnone
+ %add = fadd float %call, %call1
+ ret float %add
+}
+
+define float @test1_errno(float %x) nounwind {
+entry:
+; SINCOS-LABEL: test1_errno:
+; SINCOS: bl _sinf
+; SINCOS: bl _cosf
- %call = tail call float @sinf(float %x) nounwind readnone
- %call1 = tail call float @cosf(float %x) nounwind readnone
+; SINCOS-GNU-LABEL: test1_errno:
+; SINCOS-GNU: bl sinf
+; SINCOS-GNU: bl cosf
+
+; NOOPT-LABEL: test1_errno:
+; NOOPT: bl _sinf
+; NOOPT: bl _cosf
+
+ %call = tail call float @sinf(float %x)
+ %call1 = tail call float @cosf(float %x)
%add = fadd float %call, %call1
ret float %add
}
@@ -41,16 +59,33 @@ entry:
; NOOPT: bl _sin
; NOOPT: bl _cos
-; NOOPT-GNU-LABEL: test2:
-; NOOPT-GNU: bl sin
-; NOOPT-GNU: bl cos
- %call = tail call double @sin(double %x) nounwind readnone
- %call1 = tail call double @cos(double %x) nounwind readnone
+ %call = tail call double @sin(double %x) readnone
+ %call1 = tail call double @cos(double %x) readnone
+ %add = fadd double %call, %call1
+ ret double %add
+}
+
+define double @test2_errno(double %x) nounwind {
+entry:
+; SINCOS-LABEL: test2_errno:
+; SINCOS: bl _sin
+; SINCOS: bl _cos
+
+; SINCOS-GNU-LABEL: test2_errno:
+; SINCOS-GNU: bl sin
+; SINCOS-GNU: bl cos
+
+; NOOPT-LABEL: test2_errno:
+; NOOPT: bl _sin
+; NOOPT: bl _cos
+
+ %call = tail call double @sin(double %x)
+ %call1 = tail call double @cos(double %x)
%add = fadd double %call, %call1
ret double %add
}
-declare float @sinf(float) readonly
-declare double @sin(double) readonly
-declare float @cosf(float) readonly
-declare double @cos(double) readonly
+declare float @sinf(float)
+declare double @sin(double)
+declare float @cosf(float)
+declare double @cos(double)
diff --git a/test/CodeGen/ARM/swifterror.ll b/test/CodeGen/ARM/swifterror.ll
index 78764202f627..3fd57c592bfb 100644
--- a/test/CodeGen/ARM/swifterror.ll
+++ b/test/CodeGen/ARM/swifterror.ll
@@ -528,3 +528,31 @@ entry:
tail call void @acallee(i8* null)
ret void
}
+
+
+declare swiftcc void @foo2(%swift_error** swifterror)
+
+; Make sure we properly assign registers during fast-isel.
+; CHECK-O0-LABEL: testAssign
+; CHECK-O0: mov r8, #0
+; CHECK-O0: bl _foo2
+; CHECK-O0: str r8, [s[[STK:p.*]]]
+; CHECK-O0: ldr r0, [s[[STK]]]
+; CHECK-O0: pop
+
+; CHECK-APPLE-LABEL: testAssign
+; CHECK-APPLE: mov r8, #0
+; CHECK-APPLE: bl _foo2
+; CHECK-APPLE: mov r0, r8
+
+define swiftcc %swift_error* @testAssign(i8* %error_ref) {
+entry:
+ %error_ptr = alloca swifterror %swift_error*
+ store %swift_error* null, %swift_error** %error_ptr
+ call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
+ br label %a
+
+a:
+ %error = load %swift_error*, %swift_error** %error_ptr
+ ret %swift_error* %error
+}
diff --git a/test/CodeGen/BPF/rodata_1.ll b/test/CodeGen/BPF/rodata_1.ll
new file mode 100644
index 000000000000..5566f76bb75c
--- /dev/null
+++ b/test/CodeGen/BPF/rodata_1.ll
@@ -0,0 +1,52 @@
+; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck %s
+
+; Source code:
+; struct test_t1 {
+; char a, b, c;
+; };
+; struct test_t2 {
+; int a, b, c, d, e;
+; };
+;
+; struct test_t1 g1;
+; struct test_t2 g2;
+; int test()
+; {
+; struct test_t1 t1 = {.c = 1};
+; struct test_t2 t2 = {.c = 1};
+; g1 = t1;
+; g2 = t2;
+; return 0;
+; }
+
+%struct.test_t1 = type { i8, i8, i8 }
+%struct.test_t2 = type { i32, i32, i32, i32, i32 }
+
+@test.t1 = private unnamed_addr constant %struct.test_t1 { i8 0, i8 0, i8 1 }, align 1
+@test.t2 = private unnamed_addr constant %struct.test_t2 { i32 0, i32 0, i32 1, i32 0, i32 0 }, align 4
+@g1 = common local_unnamed_addr global %struct.test_t1 zeroinitializer, align 1
+@g2 = common local_unnamed_addr global %struct.test_t2 zeroinitializer, align 4
+
+; Function Attrs: nounwind
+define i32 @test() local_unnamed_addr #0 {
+; CHECK-LABEL: test:
+
+entry:
+ tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @g1, i64 0, i32 0), i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @test.t1, i64 0, i32 0), i64 3, i32 1, i1 false)
+ tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.test_t2* @g2 to i8*), i8* bitcast (%struct.test_t2* @test.t2 to i8*), i64 20, i32 4, i1 false)
+; CHECK: r1 = <MCOperand Expr:(g1)>ll
+; CHECK: r2 = 0
+; CHECK: *(u8 *)(r1 + 1) = r2
+; CHECK: r3 = 1
+; CHECK: *(u8 *)(r1 + 2) = r3
+; CHECK: r1 = <MCOperand Expr:(g2)>ll
+; CHECK: *(u32 *)(r1 + 8) = r3
+ ret i32 0
+}
+; CHECK: .section .rodata,"a",@progbits
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }
diff --git a/test/CodeGen/BPF/rodata_2.ll b/test/CodeGen/BPF/rodata_2.ll
new file mode 100644
index 000000000000..74b3c3640c3f
--- /dev/null
+++ b/test/CodeGen/BPF/rodata_2.ll
@@ -0,0 +1,51 @@
+; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck %s
+
+; Source code:
+; struct test_t1 {
+; char a;
+; int b;
+; };
+; struct test_t2 {
+; char a, b;
+; struct test_t1 c[2];
+; int d[2];
+; int e;
+; };
+; struct test_t2 g;
+; int test()
+; {
+; struct test_t2 t2 = {.c = {{}, {.b = 1}}, .d = {2, 3}};
+; g = t2;
+; return 0;
+; }
+
+%struct.test_t2 = type { i8, i8, [2 x %struct.test_t1], [2 x i32], i32 }
+%struct.test_t1 = type { i8, i32 }
+
+@test.t2 = private unnamed_addr constant %struct.test_t2 { i8 0, i8 0, [2 x %struct.test_t1] [%struct.test_t1 zeroinitializer, %struct.test_t1 { i8 0, i32 1 }], [2 x i32] [i32 2, i32 3], i32 0 }, align 4
+@g = common local_unnamed_addr global %struct.test_t2 zeroinitializer, align 4
+
+; Function Attrs: nounwind
+define i32 @test() local_unnamed_addr #0 {
+; CHECK-LABEL: test:
+
+entry:
+ tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.test_t2, %struct.test_t2* @g, i64 0, i32 0), i8* getelementptr inbounds (%struct.test_t2, %struct.test_t2* @test.t2, i64 0, i32 0), i64 32, i32 4, i1 false)
+; CHECK: r1 = <MCOperand Expr:(g)>ll
+; CHECK: r2 = 0
+; CHECK: *(u32 *)(r1 + 28) = r2
+; CHECK: r3 = 3
+; CHECK: *(u32 *)(r1 + 24) = r3
+; CHECK: r3 = 2
+; CHECK: *(u32 *)(r1 + 20) = r3
+; CHECK: r3 = 1
+; CHECK: *(u32 *)(r1 + 16) = r3
+ ret i32 0
+}
+; CHECK: .section .rodata.cst32,"aM",@progbits,32
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }
diff --git a/test/CodeGen/BPF/rodata_3.ll b/test/CodeGen/BPF/rodata_3.ll
new file mode 100644
index 000000000000..814ce7645465
--- /dev/null
+++ b/test/CodeGen/BPF/rodata_3.ll
@@ -0,0 +1,41 @@
+; REQUIRES: x86_64-linux
+; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck --check-prefix=CHECK-EL %s
+; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck --check-prefix=CHECK-EB %s
+;
+; This test requires little-endian host, so we specific x86_64-linux here.
+; Source code:
+; struct test_t1 {
+; char a;
+; int b, c, d;
+; };
+;
+; struct test_t1 g;
+; int test()
+; {
+; struct test_t1 t1 = {.a = 1};
+; g = t1;
+; return 0;
+; }
+
+%struct.test_t1 = type { i8, i32, i32, i32 }
+
+@test.t1 = private unnamed_addr constant %struct.test_t1 { i8 1, i32 0, i32 0, i32 0 }, align 4
+@g = common local_unnamed_addr global %struct.test_t1 zeroinitializer, align 4
+
+; Function Attrs: nounwind
+define i32 @test() local_unnamed_addr #0 {
+entry:
+ tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @g, i64 0, i32 0), i8* getelementptr inbounds (%struct.test_t1, %struct.test_t1* @test.t1, i64 0, i32 0), i64 16, i32 4, i1 false)
+; CHECK-EL: r2 = 1
+; CHECK-EL: *(u32 *)(r1 + 0) = r2
+; CHECK-EB: r2 = 16777216
+; CHECK-EB: *(u32 *)(r1 + 0) = r2
+ ret i32 0
+}
+; CHECK-EL: .section .rodata.cst16,"aM",@progbits,16
+; CHECK-EB: .section .rodata.cst16,"aM",@progbits,16
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }
diff --git a/test/CodeGen/BPF/rodata_4.ll b/test/CodeGen/BPF/rodata_4.ll
new file mode 100644
index 000000000000..d6b9fba5be0a
--- /dev/null
+++ b/test/CodeGen/BPF/rodata_4.ll
@@ -0,0 +1,43 @@
+; RUN: llc < %s -march=bpfel -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -march=bpfeb -verify-machineinstrs | FileCheck %s
+
+; Source code:
+; struct test_t1
+; {
+; short a;
+; short b;
+; char c;
+; };
+;
+; struct test_t1 g;
+; int test()
+; {
+; struct test_t1 t1[] = {{50, 500, 5}, {60, 600, 6}, {70, 700, 7}, {80, 800, 8} };
+;
+; g = t1[1];
+; return 0;
+; }
+
+%struct.test_t1 = type { i16, i16, i8 }
+
+@test.t1 = private unnamed_addr constant [4 x %struct.test_t1] [%struct.test_t1 { i16 50, i16 500, i8 5 }, %struct.test_t1 { i16 60, i16 600, i8 6 }, %struct.test_t1 { i16 70, i16 700, i8 7 }, %struct.test_t1 { i16 80, i16 800, i8 8 }], align 2
+@g = common local_unnamed_addr global %struct.test_t1 zeroinitializer, align 2
+
+; Function Attrs: nounwind
+define i32 @test() local_unnamed_addr #0 {
+; CHECK-LABEL: test:
+entry:
+ tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast (%struct.test_t1* @g to i8*), i8* bitcast (%struct.test_t1* getelementptr inbounds ([4 x %struct.test_t1], [4 x %struct.test_t1]* @test.t1, i64 0, i64 1) to i8*), i64 6, i32 2, i1 false)
+; CHECK: r2 = 600
+; CHECK: *(u16 *)(r1 + 2) = r2
+; CHECK: r2 = 60
+; CHECK: *(u16 *)(r1 + 0) = r2
+ ret i32 0
+}
+; CHECK .section .rodata,"a",@progbits
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #1
+
+attributes #0 = { nounwind }
+attributes #1 = { argmemonly nounwind }
diff --git a/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll b/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll
new file mode 100644
index 000000000000..0abf8f873200
--- /dev/null
+++ b/test/CodeGen/Hexagon/loop-idiom/pmpy-shiftconv-fail.ll
@@ -0,0 +1,48 @@
+; RUN: opt -march=hexagon -hexagon-loop-idiom -S < %s | FileCheck %s
+; REQUIRES: asserts
+;
+; Check for sane output, this used to crash.
+; CHECK: define void @fred
+
+; The conversion of shifts from right to left failed, but the return
+; code was not checked and the transformation proceeded.
+
+target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
+target triple = "hexagon"
+
+@A = common global [256 x i32] zeroinitializer, align 8
+
+; Function Attrs: noinline nounwind
+define void @fred() local_unnamed_addr #0 {
+b0:
+ br label %b1
+
+b1: ; preds = %b13, %b0
+ %v2 = phi i32 [ 0, %b0 ], [ %v16, %b13 ]
+ br label %b3
+
+b3: ; preds = %b3, %b1
+ %v4 = phi i32 [ %v2, %b1 ], [ %v10, %b3 ]
+ %v5 = phi i32 [ 0, %b1 ], [ %v11, %b3 ]
+ %v6 = and i32 %v4, 1
+ %v7 = icmp ne i32 %v6, 0
+ %v8 = lshr i32 %v4, 1
+ %v9 = xor i32 %v8, 123456789
+ %v10 = select i1 %v7, i32 %v9, i32 %v8
+ %v11 = add nuw nsw i32 %v5, 1
+ %v12 = icmp ne i32 %v11, 8
+ br i1 %v12, label %b3, label %b13
+
+b13: ; preds = %b3
+ %v14 = phi i32 [ %v10, %b3 ]
+ %v15 = getelementptr inbounds [256 x i32], [256 x i32]* @A, i32 0, i32 %v2
+ store i32 %v14, i32* %v15, align 4
+ %v16 = add nuw nsw i32 %v2, 1
+ %v17 = icmp ne i32 %v16, 256
+ br i1 %v17, label %b1, label %b18
+
+b18: ; preds = %b13
+ ret void
+}
+
+attributes #0 = { noinline nounwind "target-cpu"="hexagonv60" }
diff --git a/test/CodeGen/Hexagon/mulh.ll b/test/CodeGen/Hexagon/mulh.ll
new file mode 100644
index 000000000000..0442e28d4089
--- /dev/null
+++ b/test/CodeGen/Hexagon/mulh.ll
@@ -0,0 +1,27 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+
+target triple = "hexagon"
+
+; CHECK-LABEL: danny:
+; CHECK: r{{[0-9]+}} = mpy(r0,r1)
+define i32 @danny(i32 %a0, i32 %a1) {
+b2:
+ %v3 = sext i32 %a0 to i64
+ %v4 = sext i32 %a1 to i64
+ %v5 = mul nsw i64 %v3, %v4
+ %v6 = ashr i64 %v5, 32
+ %v7 = trunc i64 %v6 to i32
+ ret i32 %v7
+}
+
+; CHECK-LABEL: sammy:
+; CHECK: r{{[0-9]+}} = mpy(r0,r1)
+define i32 @sammy(i32 %a0, i32 %a1) {
+b2:
+ %v3 = sext i32 %a0 to i64
+ %v4 = sext i32 %a1 to i64
+ %v5 = mul nsw i64 %v3, %v4
+ %v6 = lshr i64 %v5, 32
+ %v7 = trunc i64 %v6 to i32
+ ret i32 %v7
+}
diff --git a/test/CodeGen/Hexagon/mux-kill.mir b/test/CodeGen/Hexagon/mux-kill.mir
new file mode 100644
index 000000000000..6944050e3dab
--- /dev/null
+++ b/test/CodeGen/Hexagon/mux-kill.mir
@@ -0,0 +1,15 @@
+# RUN: llc -march=hexagon -run-pass hexagon-gen-mux -o - %s -verify-machineinstrs | FileCheck %s
+# CHECK: %r2 = C2_mux %p0, %r0, %r1
+---
+name: fred
+tracksRegLiveness: true
+
+body: |
+ bb.0:
+ liveins: %d0, %p0
+
+ %r2 = A2_tfrt %p0, %r0
+ %r0 = A2_tfr %r1
+ %r2 = A2_tfrf %p0, killed %r1
+...
+
diff --git a/test/CodeGen/Hexagon/mux-kill2.mir b/test/CodeGen/Hexagon/mux-kill2.mir
new file mode 100644
index 000000000000..5f34097af7cf
--- /dev/null
+++ b/test/CodeGen/Hexagon/mux-kill2.mir
@@ -0,0 +1,17 @@
+# RUN: llc -march=hexagon -run-pass hexagon-gen-mux -o - -verify-machineinstrs %s | FileCheck %s
+# CHECK: %r1 = C2_muxri %p0, 123, %r0
+# CHECK: %r2 = C2_muxir %p0, killed %r0, 321
+---
+name: fred
+tracksRegLiveness: true
+
+body: |
+ bb.0:
+ liveins: %r0, %p0
+
+ %r2 = A2_tfrt %p0, %r0
+ %r1 = C2_cmoveit %p0, 123
+ %r1 = A2_tfrf %p0, killed %r0, implicit killed %r1
+ %r2 = C2_cmoveif killed %p0, 321, implicit killed %r2
+...
+
diff --git a/test/CodeGen/Hexagon/store-imm-stack-object.ll b/test/CodeGen/Hexagon/store-imm-stack-object.ll
new file mode 100644
index 000000000000..8de310953aee
--- /dev/null
+++ b/test/CodeGen/Hexagon/store-imm-stack-object.ll
@@ -0,0 +1,86 @@
+; RUN: llc -march=hexagon < %s | FileCheck %s
+
+target triple = "hexagon"
+
+; CHECK-LABEL: test1:
+; CHECK: [[REG1:(r[0-9]+)]] = ##875770417
+; CHECK-DAG: memw(r29+#4) = [[REG1]]
+; CHECK-DAG: memw(r29+#8) = #51
+; CHECK-DAG: memh(r29+#12) = #50
+; CHECK-DAG: memb(r29+#15) = #49
+define void @test1() {
+b0:
+ %v1 = alloca [1 x i8], align 1
+ %v2 = alloca i16, align 2
+ %v3 = alloca i32, align 4
+ %v4 = alloca i32, align 4
+ %v5 = getelementptr inbounds [1 x i8], [1 x i8]* %v1, i32 0, i32 0
+ call void @llvm.lifetime.start(i64 1, i8* %v5)
+ store i8 49, i8* %v5, align 1
+ %v6 = bitcast i16* %v2 to i8*
+ call void @llvm.lifetime.start(i64 2, i8* %v6)
+ store i16 50, i16* %v2, align 2
+ %v7 = bitcast i32* %v3 to i8*
+ call void @llvm.lifetime.start(i64 4, i8* %v7)
+ store i32 51, i32* %v3, align 4
+ %v8 = bitcast i32* %v4 to i8*
+ call void @llvm.lifetime.start(i64 4, i8* %v8)
+ store i32 875770417, i32* %v4, align 4
+ call void @test4(i8* %v5, i8* %v6, i8* %v7, i8* %v8)
+ call void @llvm.lifetime.end(i64 4, i8* %v8)
+ call void @llvm.lifetime.end(i64 4, i8* %v7)
+ call void @llvm.lifetime.end(i64 2, i8* %v6)
+ call void @llvm.lifetime.end(i64 1, i8* %v5)
+ ret void
+}
+
+; CHECK-LABEL: test2:
+; CHECK-DAG: memw(r29+#208) = #51
+; CHECK-DAG: memh(r29+#212) = r{{[0-9]+}}
+; CHECK-DAG: memb(r29+#215) = r{{[0-9]+}}
+define void @test2() {
+b0:
+ %v1 = alloca [1 x i8], align 1
+ %v2 = alloca i16, align 2
+ %v3 = alloca i32, align 4
+ %v4 = alloca i32, align 4
+ %v5 = alloca [100 x i8], align 8
+ %v6 = alloca [101 x i8], align 8
+ %v7 = getelementptr inbounds [1 x i8], [1 x i8]* %v1, i32 0, i32 0
+ call void @llvm.lifetime.start(i64 1, i8* %v7)
+ store i8 49, i8* %v7, align 1
+ %v8 = bitcast i16* %v2 to i8*
+ call void @llvm.lifetime.start(i64 2, i8* %v8)
+ store i16 50, i16* %v2, align 2
+ %v9 = bitcast i32* %v3 to i8*
+ call void @llvm.lifetime.start(i64 4, i8* %v9)
+ store i32 51, i32* %v3, align 4
+ %v10 = bitcast i32* %v4 to i8*
+ call void @llvm.lifetime.start(i64 4, i8* %v10)
+ store i32 875770417, i32* %v4, align 4
+ %v11 = getelementptr inbounds [100 x i8], [100 x i8]* %v5, i32 0, i32 0
+ call void @llvm.lifetime.start(i64 100, i8* %v11)
+ call void @llvm.memset.p0i8.i32(i8* %v11, i8 0, i32 100, i32 8, i1 false)
+ store i8 50, i8* %v11, align 8
+ %v12 = getelementptr inbounds [101 x i8], [101 x i8]* %v6, i32 0, i32 0
+ call void @llvm.lifetime.start(i64 101, i8* %v12)
+ call void @llvm.memset.p0i8.i32(i8* %v12, i8 0, i32 101, i32 8, i1 false)
+ store i8 49, i8* %v12, align 8
+ call void @test3(i8* %v7, i8* %v8, i8* %v9, i8* %v10, i8* %v11, i8* %v12)
+ call void @llvm.lifetime.end(i64 101, i8* %v12)
+ call void @llvm.lifetime.end(i64 100, i8* %v11)
+ call void @llvm.lifetime.end(i64 4, i8* %v10)
+ call void @llvm.lifetime.end(i64 4, i8* %v9)
+ call void @llvm.lifetime.end(i64 2, i8* %v8)
+ call void @llvm.lifetime.end(i64 1, i8* %v7)
+ ret void
+}
+
+declare void @llvm.lifetime.start(i64, i8* nocapture) #0
+declare void @llvm.lifetime.end(i64, i8* nocapture) #0
+declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i32, i1) #0
+
+declare void @test3(i8*, i8*, i8*, i8*, i8*, i8*)
+declare void @test4(i8*, i8*, i8*, i8*)
+
+attributes #0 = { argmemonly nounwind "target-cpu"="hexagonv60" }
diff --git a/test/CodeGen/Mips/2008-06-05-Carry.ll b/test/CodeGen/Mips/2008-06-05-Carry.ll
index c61e1cdedea7..5e6092fc7848 100644
--- a/test/CodeGen/Mips/2008-06-05-Carry.ll
+++ b/test/CodeGen/Mips/2008-06-05-Carry.ll
@@ -2,20 +2,21 @@
define i64 @add64(i64 %u, i64 %v) nounwind {
entry:
+; CHECK-LABEL: add64:
; CHECK: addu
-; CHECK: sltu
+; CHECK-DAG: sltu
+; CHECK-DAG: addu
; CHECK: addu
-; CHECK: addu
- %tmp2 = add i64 %u, %v
+ %tmp2 = add i64 %u, %v
ret i64 %tmp2
}
define i64 @sub64(i64 %u, i64 %v) nounwind {
entry:
-; CHECK: sub64
+; CHECK-LABEL: sub64
+; CHECK-DAG: sltu
+; CHECK-DAG: subu
; CHECK: subu
-; CHECK: sltu
-; CHECK: addu
; CHECK: subu
%tmp2 = sub i64 %u, %v
ret i64 %tmp2
diff --git a/test/CodeGen/Mips/brundef.ll b/test/CodeGen/Mips/brundef.ll
new file mode 100644
index 000000000000..802556c7cabd
--- /dev/null
+++ b/test/CodeGen/Mips/brundef.ll
@@ -0,0 +1,26 @@
+; RUN: llc -march=mips -mcpu=mips32 -verify-machineinstrs -o /dev/null < %s
+; Confirm that MachineInstr branch simplification preserves
+; register operand flags, such as the <undef> flag.
+
+define void @ham() {
+bb:
+ %tmp = alloca i32, align 4
+ %tmp13 = ptrtoint i32* %tmp to i32
+ %tmp70 = icmp eq i32 undef, -1
+ br i1 %tmp70, label %bb72, label %bb40
+
+bb72: ; preds = %bb72, %bb
+ br i1 undef, label %bb40, label %bb72
+
+bb40: ; preds = %bb72, %bb
+ %tmp41 = phi i32 [ %tmp13, %bb72 ], [ %tmp13, %bb ]
+ %tmp55 = inttoptr i32 %tmp41 to i32*
+ %tmp58 = insertelement <2 x i32*> undef, i32* %tmp55, i32 1
+ br label %bb59
+
+bb59: ; preds = %bb59, %bb40
+ %tmp60 = phi <2 x i32*> [ %tmp61, %bb59 ], [ %tmp58, %bb40 ]
+ %tmp61 = getelementptr i32, <2 x i32*> %tmp60, <2 x i32> <i32 -1, i32 1>
+ %tmp62 = extractelement <2 x i32*> %tmp61, i32 1
+ br label %bb59
+}
diff --git a/test/CodeGen/Mips/dsp-patterns.ll b/test/CodeGen/Mips/dsp-patterns.ll
index 837c0d8bfc52..250d3eff37dc 100644
--- a/test/CodeGen/Mips/dsp-patterns.ll
+++ b/test/CodeGen/Mips/dsp-patterns.ll
@@ -1,5 +1,5 @@
-; RUN: llc -march=mips -mattr=dsp < %s | FileCheck %s -check-prefix=R1
-; RUN: llc -march=mips -mattr=dspr2 < %s | FileCheck %s -check-prefix=R2
+; RUN: llc -march=mips -mcpu=mips32r2 -mattr=dsp < %s | FileCheck %s -check-prefix=R1
+; RUN: llc -march=mips -mcpu=mips32r2 -mattr=dspr2 < %s | FileCheck %s -check-prefix=R2
; R1-LABEL: test_lbux:
; R1: lbux ${{[0-9]+}}
diff --git a/test/CodeGen/Mips/llcarry.ll b/test/CodeGen/Mips/llcarry.ll
index fcf129420234..b7cc6fc8ea75 100644
--- a/test/CodeGen/Mips/llcarry.ll
+++ b/test/CodeGen/Mips/llcarry.ll
@@ -14,9 +14,9 @@ entry:
%add = add nsw i64 %1, %0
store i64 %add, i64* @k, align 8
; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
-; 16: sltu ${{[0-9]+}}, ${{[0-9]+}}
-; 16: move ${{[0-9]+}}, $t8
; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
+; 16: sltu ${{[0-9]+}}, ${{[0-9]+}}
+; 16: move ${{[0-9]+}}, $24
; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
ret void
}
@@ -28,8 +28,8 @@ entry:
%sub = sub nsw i64 %0, %1
; 16: subu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
; 16: sltu ${{[0-9]+}}, ${{[0-9]+}}
-; 16: move ${{[0-9]+}}, $t8
-; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
+; 16: move ${{[0-9]+}}, $24
+; 16: subu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
; 16: subu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
store i64 %sub, i64* @l, align 8
ret void
@@ -41,8 +41,7 @@ entry:
%add = add nsw i64 %0, 15
; 16: addiu ${{[0-9]+}}, 15
; 16: sltu ${{[0-9]+}}, ${{[0-9]+}}
-; 16: move ${{[0-9]+}}, $t8
-; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
+; 16: move ${{[0-9]+}}, $24
; 16: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
store i64 %add, i64* @m, align 8
ret void
diff --git a/test/CodeGen/Mips/llvm-ir/add.ll b/test/CodeGen/Mips/llvm-ir/add.ll
index a5ecdda94ce2..63884eb03b8c 100644
--- a/test/CodeGen/Mips/llvm-ir/add.ll
+++ b/test/CodeGen/Mips/llvm-ir/add.ll
@@ -1,35 +1,35 @@
; RUN: llc < %s -march=mips -mcpu=mips2 | FileCheck %s \
-; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32
+; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32,PRE4
; RUN: llc < %s -march=mips -mcpu=mips32 | FileCheck %s \
-; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32
+; RUN: -check-prefixes=ALL,NOT-R2-R6,GP32,GP32-CMOV
; RUN: llc < %s -march=mips -mcpu=mips32r2 | FileCheck %s \
-; RUN: -check-prefixes=ALL,R2-R6,GP32
+; RUN: -check-prefixes=ALL,R2-R6,GP32,GP32-CMOV
; RUN: llc < %s -march=mips -mcpu=mips32r3 | FileCheck %s \
-; RUN: -check-prefixes=ALL,R2-R6,GP32
+; RUN: -check-prefixes=ALL,R2-R6,GP32,GP32-CMOV
; RUN: llc < %s -march=mips -mcpu=mips32r5 | FileCheck %s \
-; RUN: -check-prefixes=ALL,R2-R6,GP32
+; RUN: -check-prefixes=ALL,R2-R6,GP32,GP32-CMOV
; RUN: llc < %s -march=mips -mcpu=mips32r6 | FileCheck %s \
; RUN: -check-prefixes=ALL,R2-R6,GP32
; RUN: llc < %s -march=mips64 -mcpu=mips3 | FileCheck %s \
-; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64
+; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64,GP64-NOT-R2-R6
; RUN: llc < %s -march=mips64 -mcpu=mips4 | FileCheck %s \
-; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64
+; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64,GP64-NOT-R2-R6
; RUN: llc < %s -march=mips64 -mcpu=mips64 | FileCheck %s \
-; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64
+; RUN: -check-prefixes=ALL,NOT-R2-R6,GP64,GP64-NOT-R2-R6
; RUN: llc < %s -march=mips64 -mcpu=mips64r2 | FileCheck %s \
-; RUN: -check-prefixes=ALL,R2-R6,GP64
+; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6
; RUN: llc < %s -march=mips64 -mcpu=mips64r3 | FileCheck %s \
-; RUN: -check-prefixes=ALL,R2-R6,GP64
+; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6
; RUN: llc < %s -march=mips64 -mcpu=mips64r5 | FileCheck %s \
-; RUN: -check-prefixes=ALL,R2-R6,GP64
+; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6
; RUN: llc < %s -march=mips64 -mcpu=mips64r6 | FileCheck %s \
-; RUN: -check-prefixes=ALL,R2-R6,GP64
+; RUN: -check-prefixes=ALL,R2-R6,GP64,GP64-R2-R6
; RUN: llc < %s -march=mips -mcpu=mips32r3 -mattr=+micromips -O2 -verify-machineinstrs | FileCheck %s \
-; RUN: -check-prefixes=ALL,MMR6,MM32
+; RUN: -check-prefixes=ALL,MMR3,MM32
; RUN: llc < %s -march=mips -mcpu=mips32r6 -mattr=+micromips -O2 | FileCheck %s \
; RUN: -check-prefixes=ALL,MMR6,MM32
; RUN: llc < %s -march=mips -mcpu=mips64r6 -target-abi n64 -mattr=+micromips -O2 | FileCheck %s \
-; RUN: -check-prefixes=ALL,MMR6,MM64
+; RUN: -check-prefixes=ALL,MM64
; FIXME: This code sequence is inefficient as it should be 'subu $[[T0]], $zero, $[[T0]'.
@@ -110,17 +110,17 @@ define signext i64 @add_i64(i64 signext %a, i64 signext %b) {
entry:
; ALL-LABEL: add_i64:
- ; GP32: addu $3, $5, $7
- ; GP32: sltu $[[T0:[0-9]+]], $3, $7
- ; GP32: addu $[[T1:[0-9]+]], $[[T0]], $6
- ; GP32: addu $2, $4, $[[T1]]
+ ; GP32-DAG: addu $[[T0:[0-9]+]], $4, $6
+ ; GP32-DAG: addu $3, $5, $7
+ ; GP32: sltu $[[T1:[0-9]+]], $3, $5
+ ; GP32: addu $2, $[[T0]], $[[T1]]
; GP64: daddu $2, $4, $5
- ; MM32: addu16 $3, $5, $7
- ; MM32: sltu $[[T0:[0-9]+]], $3, $7
- ; MM32: addu $[[T1:[0-9]+]], $[[T0]], $6
- ; MM32: addu $2, $4, $[[T1]]
+ ; MM32-DAG: addu16 $3, $5, $7
+ ; MM32-DAG: addu16 $[[T0:[0-9]+]], $4, $6
+ ; MM32: sltu $[[T1:[0-9]+]], $3, $5
+ ; MM32: addu16 $2, $[[T0]], $[[T1]]
; MM64: daddu $2, $4, $5
@@ -132,49 +132,108 @@ define signext i128 @add_i128(i128 signext %a, i128 signext %b) {
entry:
; ALL-LABEL: add_i128:
- ; GP32: lw $[[T0:[0-9]+]], 28($sp)
- ; GP32: addu $[[T1:[0-9]+]], $7, $[[T0]]
- ; GP32: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]]
- ; GP32: lw $[[T3:[0-9]+]], 24($sp)
- ; GP32: addu $[[T4:[0-9]+]], $[[T2]], $[[T3]]
- ; GP32: addu $[[T5:[0-9]+]], $6, $[[T4]]
- ; GP32: sltu $[[T6:[0-9]+]], $[[T5]], $[[T3]]
- ; GP32: lw $[[T7:[0-9]+]], 20($sp)
- ; GP32: addu $[[T8:[0-9]+]], $[[T6]], $[[T7]]
- ; GP32: lw $[[T9:[0-9]+]], 16($sp)
- ; GP32: addu $3, $5, $[[T8]]
- ; GP32: sltu $[[T10:[0-9]+]], $3, $[[T7]]
- ; GP32: addu $[[T11:[0-9]+]], $[[T10]], $[[T9]]
- ; GP32: addu $2, $4, $[[T11]]
- ; GP32: move $4, $[[T5]]
- ; GP32: move $5, $[[T1]]
-
- ; GP64: daddu $3, $5, $7
- ; GP64: sltu $[[T0:[0-9]+]], $3, $7
- ; GP64: daddu $[[T1:[0-9]+]], $[[T0]], $6
- ; GP64: daddu $2, $4, $[[T1]]
-
- ; MM32: lw $[[T0:[0-9]+]], 28($sp)
- ; MM32: addu $[[T1:[0-9]+]], $7, $[[T0]]
- ; MM32: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]]
- ; MM32: lw $[[T3:[0-9]+]], 24($sp)
- ; MM32: addu16 $[[T4:[0-9]+]], $[[T2]], $[[T3]]
- ; MM32: addu16 $[[T5:[0-9]+]], $6, $[[T4]]
- ; MM32: sltu $[[T6:[0-9]+]], $[[T5]], $[[T3]]
- ; MM32: lw $[[T7:[0-9]+]], 20($sp)
- ; MM32: addu16 $[[T8:[0-9]+]], $[[T6]], $[[T7]]
- ; MM32: lw $[[T9:[0-9]+]], 16($sp)
- ; MM32: addu16 $[[T10:[0-9]+]], $5, $[[T8]]
- ; MM32: sltu $[[T11:[0-9]+]], $[[T10]], $[[T7]]
- ; MM32: addu $[[T12:[0-9]+]], $[[T11]], $[[T9]]
- ; MM32: addu16 $[[T13:[0-9]+]], $4, $[[T12]]
- ; MM32: move $4, $[[T5]]
- ; MM32: move $5, $[[T1]]
-
+ ; PRE4: move $[[R1:[0-9]+]], $5
+ ; PRE4: move $[[R2:[0-9]+]], $4
+ ; PRE4: lw $[[R3:[0-9]+]], 24($sp)
+ ; PRE4: addu $[[R4:[0-9]+]], $6, $[[R3]]
+ ; PRE4: lw $[[R5:[0-9]+]], 28($sp)
+ ; PRE4: addu $[[R6:[0-9]+]], $7, $[[R5]]
+ ; PRE4: sltu $[[R7:[0-9]+]], $[[R6]], $7
+ ; PRE4: addu $[[R8:[0-9]+]], $[[R4]], $[[R7]]
+ ; PRE4: xor $[[R9:[0-9]+]], $[[R8]], $6
+ ; PRE4: sltiu $[[R10:[0-9]+]], $[[R9]], 1
+ ; PRE4: bnez $[[R10]], $BB5_2
+ ; PRE4: sltu $[[R7]], $[[R8]], $6
+ ; PRE4: lw $[[R12:[0-9]+]], 20($sp)
+ ; PRE4: addu $[[R13:[0-9]+]], $[[R1]], $[[R12]]
+ ; PRE4: lw $[[R14:[0-9]+]], 16($sp)
+ ; PRE4: addu $[[R15:[0-9]+]], $[[R13]], $[[R7]]
+ ; PRE4: addu $[[R16:[0-9]+]], $[[R2]], $[[R14]]
+ ; PRE4: sltu $[[R17:[0-9]+]], $[[R15]], $[[R13]]
+ ; PRE4: sltu $[[R18:[0-9]+]], $[[R13]], $[[R1]]
+ ; PRE4: addu $[[R19:[0-9]+]], $[[R16]], $[[R18]]
+ ; PRE4: addu $2, $[[R19]], $[[R17]]
+
+ ; GP32-CMOV: lw $[[T0:[0-9]+]], 24($sp)
+ ; GP32-CMOV: addu $[[T1:[0-9]+]], $6, $[[T0]]
+ ; GP32-CMOV: lw $[[T2:[0-9]+]], 28($sp)
+ ; GP32-CMOV: addu $[[T3:[0-9]+]], $7, $[[T2]]
+ ; GP32-CMOV: sltu $[[T4:[0-9]+]], $[[T3]], $7
+ ; GP32-CMOV: addu $[[T5:[0-9]+]], $[[T1]], $[[T4]]
+ ; GP32-CMOV: sltu $[[T6:[0-9]+]], $[[T5]], $6
+ ; GP32-CMOV: xor $[[T7:[0-9]+]], $[[T5]], $6
+ ; GP32-CMOV: movz $[[T8:[0-9]+]], $[[T4]], $[[T7]]
+ ; GP32-CMOV: lw $[[T9:[0-9]+]], 20($sp)
+ ; GP32-CMOV: addu $[[T10:[0-9]+]], $5, $[[T4]]
+ ; GP32-CMOV: addu $[[T11:[0-9]+]], $[[T10]], $[[T8]]
+ ; GP32-CMOV: lw $[[T12:[0-9]+]], 16($sp)
+ ; GP32-CMOV: sltu $[[T13:[0-9]+]], $[[T11]], $[[T10]]
+ ; GP32-CMOV: addu $[[T14:[0-9]+]], $4, $[[T12]]
+ ; GP32-CMOV: sltu $[[T15:[0-9]+]], $[[T10]], $5
+ ; GP32-CMOV: addu $[[T16:[0-9]+]], $[[T14]], $[[T15]]
+ ; GP32-CMOV: addu $[[T17:[0-9]+]], $[[T16]], $[[T13]]
+ ; GP32-CMOV: move $4, $[[T5]]
+ ; GP32-CMOV: move $5, $[[T3]]
+
+ ; GP64: daddu $[[T0:[0-9]+]], $4, $6
+ ; GP64: daddu $[[T1:[0-9]+]], $5, $7
+ ; GP64: sltu $[[T2:[0-9]+]], $[[T1]], $5
+ ; GP64-NOT-R2-R6: dsll $[[T3:[0-9]+]], $[[T2]], 32
+ ; GP64-NOT-R2-R6: dsrl $[[T4:[0-9]+]], $[[T3]], 32
+ ; GP64-R2-R6: dext $[[T4:[0-9]+]], $[[T2]], 0, 32
+
+ ; GP64: daddu $2, $[[T0]], $[[T4]]
+
+ ; MMR3: move $[[T1:[0-9]+]], $5
+ ; MMR3-DAG: lw $[[T2:[0-9]+]], 32($sp)
+ ; MMR3: addu16 $[[T3:[0-9]+]], $6, $[[T2]]
+ ; MMR3-DAG: lw $[[T4:[0-9]+]], 36($sp)
+ ; MMR3: addu16 $[[T5:[0-9]+]], $7, $[[T4]]
+ ; MMR3: sltu $[[T6:[0-9]+]], $[[T5]], $7
+ ; MMR3: addu16 $[[T7:[0-9]+]], $[[T3]], $[[T6]]
+ ; MMR3: sltu $[[T8:[0-9]+]], $[[T7]], $6
+ ; MMR3: xor $[[T9:[0-9]+]], $[[T7]], $6
+ ; MMR3: movz $[[T8]], $[[T6]], $[[T9]]
+ ; MMR3: lw $[[T10:[0-9]+]], 28($sp)
+ ; MMR3: addu16 $[[T11:[0-9]+]], $[[T1]], $[[T10]]
+ ; MMR3: addu16 $[[T12:[0-9]+]], $[[T11]], $[[T8]]
+ ; MMR3: lw $[[T13:[0-9]+]], 24($sp)
+ ; MMR3: sltu $[[T14:[0-9]+]], $[[T12]], $[[T11]]
+ ; MMR3: addu16 $[[T15:[0-9]+]], $4, $[[T13]]
+ ; MMR3: sltu $[[T16:[0-9]+]], $[[T11]], $[[T1]]
+ ; MMR3: addu16 $[[T17:[0-9]+]], $[[T15]], $[[T16]]
+ ; MMR3: addu16 $2, $2, $[[T14]]
+
+ ; MMR6: move $[[T1:[0-9]+]], $5
+ ; MMR6: move $[[T2:[0-9]+]], $4
+ ; MMR6: lw $[[T3:[0-9]+]], 32($sp)
+ ; MMR6: addu16 $[[T4:[0-9]+]], $6, $[[T3]]
+ ; MMR6: lw $[[T5:[0-9]+]], 36($sp)
+ ; MMR6: addu16 $[[T6:[0-9]+]], $7, $[[T5]]
+ ; MMR6: sltu $[[T7:[0-9]+]], $[[T6]], $7
+ ; MMR6: addu16 $[[T8:[0-9]+]], $[[T4]], $7
+ ; MMR6: sltu $[[T9:[0-9]+]], $[[T8]], $6
+ ; MMR6: xor $[[T10:[0-9]+]], $[[T4]], $6
+ ; MMR6: sltiu $[[T11:[0-9]+]], $[[T10]], 1
+ ; MMR6: seleqz $[[T12:[0-9]+]], $[[T9]], $[[T11]]
+ ; MMR6: selnez $[[T13:[0-9]+]], $[[T7]], $[[T11]]
+ ; MMR6: lw $[[T14:[0-9]+]], 24($sp)
+ ; MMR6: or $[[T15:[0-9]+]], $[[T13]], $[[T12]]
+ ; MMR6: addu16 $[[T16:[0-9]+]], $[[T2]], $[[T14]]
+ ; MMR6: lw $[[T17:[0-9]+]], 28($sp)
+ ; MMR6: addu16 $[[T18:[0-9]+]], $[[T1]], $[[T17]]
+ ; MMR6: addu16 $[[T19:[0-9]+]], $[[T18]], $[[T15]]
+ ; MMR6: sltu $[[T20:[0-9]+]], $[[T18]], $[[T1]]
+ ; MMR6: sltu $[[T21:[0-9]+]], $[[T17]], $[[T18]]
+ ; MMR6: addu16 $2, $[[T16]], $[[T20]]
+ ; MMR6: addu16 $2, $[[T20]], $[[T21]]
+
+ ; MM64: daddu $[[T0:[0-9]+]], $4, $6
; MM64: daddu $3, $5, $7
- ; MM64: sltu $[[T0:[0-9]+]], $3, $7
- ; MM64: daddu $[[T1:[0-9]+]], $[[T0]], $6
- ; MM64: daddu $2, $4, $[[T1]]
+ ; MM64: sltu $[[T1:[0-9]+]], $3, $5
+ ; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32
+ ; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+ ; MM64: daddu $2, $[[T0]], $[[T3]]
%r = add i128 %a, %b
ret i128 %r
@@ -249,17 +308,16 @@ define signext i32 @add_i32_4(i32 signext %a) {
define signext i64 @add_i64_4(i64 signext %a) {
; ALL-LABEL: add_i64_4:
- ; GP32: addiu $[[T0:[0-9]+]], $5, 4
- ; GP32: addiu $[[T1:[0-9]+]], $zero, 4
- ; GP32: sltu $[[T1]], $[[T0]], $[[T1]]
- ; GP32: addu $2, $4, $[[T1]]
+ ; GP32: addiu $3, $5, 4
+ ; GP32: sltu $[[T0:[0-9]+]], $3, $5
+ ; GP32: addu $2, $4, $[[T0]]
+
+ ; MM32: addiur2 $[[T1:[0-9]+]], $5, 4
+ ; MM32: sltu $[[T2:[0-9]+]], $[[T1]], $5
+ ; MM32: addu16 $2, $4, $[[T2]]
; GP64: daddiu $2, $4, 4
- ; MM32: addiu $[[T0:[0-9]+]], $5, 4
- ; MM32: li16 $[[T1:[0-9]+]], 4
- ; MM32: sltu $[[T2:[0-9]+]], $[[T0]], $[[T1]]
- ; MM32: addu $2, $4, $[[T2]]
; MM64: daddiu $2, $4, 4
@@ -270,38 +328,67 @@ define signext i64 @add_i64_4(i64 signext %a) {
define signext i128 @add_i128_4(i128 signext %a) {
; ALL-LABEL: add_i128_4:
- ; GP32: addiu $[[T0:[0-9]+]], $7, 4
- ; GP32: addiu $[[T1:[0-9]+]], $zero, 4
- ; GP32: sltu $[[T1]], $[[T0]], $[[T1]]
- ; GP32: addu $[[T2:[0-9]+]], $6, $[[T1]]
- ; GP32: sltu $[[T1]], $[[T2]], $zero
- ; GP32: addu $[[T3:[0-9]+]], $5, $[[T1]]
- ; GP32: sltu $[[T1]], $[[T3]], $zero
- ; GP32: addu $[[T1]], $4, $[[T1]]
- ; GP32: move $4, $[[T2]]
- ; GP32: move $5, $[[T0]]
-
- ; GP64: daddiu $[[T0:[0-9]+]], $5, 4
- ; GP64: daddiu $[[T1:[0-9]+]], $zero, 4
- ; GP64: sltu $[[T1]], $[[T0]], $[[T1]]
- ; GP64: daddu $2, $4, $[[T1]]
-
- ; MM32: addiu $[[T0:[0-9]+]], $7, 4
- ; MM32: li16 $[[T1:[0-9]+]], 4
- ; MM32: sltu $[[T1]], $[[T0]], $[[T1]]
- ; MM32: addu16 $[[T2:[0-9]+]], $6, $[[T1]]
- ; MM32: li16 $[[T1]], 0
- ; MM32: sltu $[[T3:[0-9]+]], $[[T2]], $[[T1]]
- ; MM32: addu16 $[[T3]], $5, $[[T3]]
- ; MM32: sltu $[[T1]], $[[T3]], $[[T1]]
- ; MM32: addu16 $[[T1]], $4, $[[T1]]
- ; MM32: move $4, $[[T2]]
- ; MM32: move $5, $[[T0]]
+ ; PRE4: move $[[T0:[0-9]+]], $5
+ ; PRE4: addiu $[[T1:[0-9]+]], $7, 4
+ ; PRE4: sltu $[[T2:[0-9]+]], $[[T1]], $7
+ ; PRE4: xori $[[T3:[0-9]+]], $[[T2]], 1
+ ; PRE4: bnez $[[T3]], $BB[[BB0:[0-9_]+]]
+ ; PRE4: addu $[[T4:[0-9]+]], $6, $[[T2]]
+ ; PRE4: sltu $[[T5:[0-9]+]], $[[T4]], $6
+ ; PRE4; $BB[[BB0:[0-9]+]]:
+ ; PRE4: addu $[[T6:[0-9]+]], $[[T0]], $[[T5]]
+ ; PRE4: sltu $[[T7:[0-9]+]], $[[T6]], $[[T0]]
+ ; PRE4: addu $[[T8:[0-9]+]], $4, $[[T7]]
+ ; PRE4: move $4, $[[T4]]
+
+ ; GP32-CMOV: addiu $[[T0:[0-9]+]], $7, 4
+ ; GP32-CMOV: sltu $[[T1:[0-9]+]], $[[T0]], $7
+ ; GP32-CMOV: addu $[[T2:[0-9]+]], $6, $[[T1]]
+ ; GP32-CMOV: sltu $[[T3:[0-9]+]], $[[T2]], $6
+ ; GP32-CMOV: movz $[[T3]], $[[T1]], $[[T1]]
+ ; GP32-CMOV: addu $[[T4:[0-9]+]], $5, $[[T3]]
+ ; GP32-CMOV: sltu $[[T5:[0-9]+]], $[[T4]], $5
+ ; GP32-CMOV: addu $[[T7:[0-9]+]], $4, $[[T5]]
+ ; GP32-CMOV: move $4, $[[T2]]
+ ; GP32-CMOV: move $5, $[[T0]]
+
+ ; GP64: daddiu $[[T0:[0-9]+]], $5, 4
+ ; GP64: sltu $[[T1:[0-9]+]], $[[T0]], $5
+ ; GP64-NOT-R2-R6: dsll $[[T2:[0-9]+]], $[[T1]], 32
+ ; GP64-NOT-R2-R6: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+ ; GP64-R2-R6: dext $[[T3:[0-9]+]], $[[T1]], 0, 32
+
+ ; GP64: daddu $2, $4, $[[T3]]
+
+ ; MMR3: addiur2 $[[T0:[0-9]+]], $7, 4
+ ; MMR3: sltu $[[T1:[0-9]+]], $[[T0]], $7
+ ; MMR3: sltu $[[T2:[0-9]+]], $[[T0]], $7
+ ; MMR3: addu16 $[[T3:[0-9]+]], $6, $[[T2]]
+ ; MMR3: sltu $[[T4:[0-9]+]], $[[T3]], $6
+ ; MMR3: movz $[[T4]], $[[T2]], $[[T1]]
+ ; MMR3: addu16 $[[T6:[0-9]+]], $5, $[[T4]]
+ ; MMR3: sltu $[[T7:[0-9]+]], $[[T6]], $5
+ ; MMR3: addu16 $2, $4, $[[T7]]
+
+ ; MMR6: addiur2 $[[T1:[0-9]+]], $7, 4
+ ; MMR6: sltu $[[T2:[0-9]+]], $[[T1]], $7
+ ; MMR6: xori $[[T3:[0-9]+]], $[[T2]], 1
+ ; MMR6: selnez $[[T4:[0-9]+]], $[[T2]], $[[T3]]
+ ; MMR6: addu16 $[[T5:[0-9]+]], $6, $[[T2]]
+ ; MMR6: sltu $[[T6:[0-9]+]], $[[T5]], $6
+ ; MMR6: seleqz $[[T7:[0-9]+]], $[[T6]], $[[T3]]
+ ; MMR6: or $[[T8:[0-9]+]], $[[T4]], $[[T7]]
+ ; MMR6: addu16 $[[T9:[0-9]+]], $5, $[[T8]]
+ ; MMR6: sltu $[[T10:[0-9]+]], $[[T9]], $5
+ ; MMR6: addu16 $[[T11:[0-9]+]], $4, $[[T10]]
+ ; MMR6: move $4, $7
+ ; MMR6: move $5, $[[T1]]
; MM64: daddiu $[[T0:[0-9]+]], $5, 4
- ; MM64: daddiu $[[T1:[0-9]+]], $zero, 4
- ; MM64: sltu $[[T1]], $[[T0]], $[[T1]]
- ; MM64: daddu $2, $4, $[[T1]]
+ ; MM64: sltu $[[T1:[0-9]+]], $[[T0]], $5
+ ; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32
+ ; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+ ; MM64: daddu $2, $4, $[[T3]]
%r = add i128 4, %a
ret i128 %r
@@ -380,16 +467,15 @@ define signext i64 @add_i64_3(i64 signext %a) {
; ALL-LABEL: add_i64_3:
; GP32: addiu $[[T0:[0-9]+]], $5, 3
- ; GP32: addiu $[[T1:[0-9]+]], $zero, 3
- ; GP32: sltu $[[T1]], $[[T0]], $[[T1]]
+ ; GP32: sltu $[[T1:[0-9]+]], $[[T0]], $5
; GP32: addu $2, $4, $[[T1]]
; GP64: daddiu $2, $4, 3
- ; MM32: addiu $[[T0:[0-9]+]], $5, 3
- ; MM32: li16 $[[T1:[0-9]+]], 3
- ; MM32: sltu $[[T2:[0-9]+]], $[[T0]], $[[T1]]
- ; MM32: addu $2, $4, $[[T2]]
+ ; MM32: move $[[T1:[0-9]+]], $5
+ ; MM32: addius5 $[[T1]], 3
+ ; MM32: sltu $[[T2:[0-9]+]], $[[T1]], $5
+ ; MM32: addu16 $2, $4, $[[T2]]
; MM64: daddiu $2, $4, 3
@@ -400,38 +486,70 @@ define signext i64 @add_i64_3(i64 signext %a) {
define signext i128 @add_i128_3(i128 signext %a) {
; ALL-LABEL: add_i128_3:
- ; GP32: addiu $[[T0:[0-9]+]], $7, 3
- ; GP32: addiu $[[T1:[0-9]+]], $zero, 3
- ; GP32: sltu $[[T1]], $[[T0]], $[[T1]]
- ; GP32: addu $[[T2:[0-9]+]], $6, $[[T1]]
- ; GP32: sltu $[[T3:[0-9]+]], $[[T2]], $zero
- ; GP32: addu $[[T4:[0-9]+]], $5, $[[T3]]
- ; GP32: sltu $[[T5:[0-9]+]], $[[T4]], $zero
- ; GP32: addu $[[T5]], $4, $[[T5]]
- ; GP32: move $4, $[[T2]]
- ; GP32: move $5, $[[T0]]
-
- ; GP64: daddiu $[[T0:[0-9]+]], $5, 3
- ; GP64: daddiu $[[T1:[0-9]+]], $zero, 3
- ; GP64: sltu $[[T1]], $[[T0]], $[[T1]]
- ; GP64: daddu $2, $4, $[[T1]]
-
- ; MM32: addiu $[[T0:[0-9]+]], $7, 3
- ; MM32: li16 $[[T1:[0-9]+]], 3
- ; MM32: sltu $[[T1]], $[[T0]], $[[T1]]
- ; MM32: addu16 $[[T2:[0-9]+]], $6, $[[T1]]
- ; MM32: li16 $[[T3:[0-9]+]], 0
- ; MM32: sltu $[[T4:[0-9]+]], $[[T2]], $[[T3]]
- ; MM32: addu16 $[[T4]], $5, $[[T4]]
- ; MM32: sltu $[[T5:[0-9]+]], $[[T4]], $[[T3]]
- ; MM32: addu16 $[[T5]], $4, $[[T5]]
- ; MM32: move $4, $[[T2]]
- ; MM32: move $5, $[[T0]]
+ ; PRE4: move $[[T0:[0-9]+]], $5
+ ; PRE4: addiu $[[T1:[0-9]+]], $7, 3
+ ; PRE4: sltu $[[T2:[0-9]+]], $[[T1]], $7
+ ; PRE4: xori $[[T3:[0-9]+]], $[[T2]], 1
+ ; PRE4: bnez $[[T3]], $BB[[BB0:[0-9_]+]]
+ ; PRE4: addu $[[T4:[0-9]+]], $6, $[[T2]]
+ ; PRE4: sltu $[[T5:[0-9]+]], $[[T4]], $6
+ ; PRE4; $BB[[BB0:[0-9]+]]:
+ ; PRE4: addu $[[T6:[0-9]+]], $[[T0]], $[[T5]]
+ ; PRE4: sltu $[[T7:[0-9]+]], $[[T6]], $[[T0]]
+ ; PRE4: addu $[[T8:[0-9]+]], $4, $[[T7]]
+ ; PRE4: move $4, $[[T4]]
+
+ ; GP32-CMOV: addiu $[[T0:[0-9]+]], $7, 3
+ ; GP32-CMOV: sltu $[[T1:[0-9]+]], $[[T0]], $7
+ ; GP32-CMOV: addu $[[T2:[0-9]+]], $6, $[[T1]]
+ ; GP32-CMOV: sltu $[[T3:[0-9]+]], $[[T2]], $6
+ ; GP32-CMOV: movz $[[T3]], $[[T1]], $[[T1]]
+ ; GP32-CMOV: addu $[[T4:[0-9]+]], $5, $[[T3]]
+ ; GP32-CMOV: sltu $[[T5:[0-9]+]], $[[T4]], $5
+ ; GP32-CMOV: addu $[[T7:[0-9]+]], $4, $[[T5]]
+ ; GP32-CMOV: move $4, $[[T2]]
+ ; GP32-CMOV: move $5, $[[T0]]
+
+ ; GP64: daddiu $[[T0:[0-9]+]], $5, 3
+ ; GP64: sltu $[[T1:[0-9]+]], $[[T0]], $5
+
+ ; GP64-NOT-R2-R6: dsll $[[T2:[0-9]+]], $[[T1]], 32
+ ; GP64-NOT-R2-R6: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+ ; GP64-R2-R6: dext $[[T3:[0-9]+]], $[[T1]], 0, 32
+
+ ; GP64: daddu $2, $4, $[[T3]]
+
+ ; MMR3: move $[[T1:[0-9]+]], $7
+ ; MMR3: addius5 $[[T1]], 3
+ ; MMR3: sltu $[[T2:[0-9]+]], $[[T1]], $7
+ ; MMR3: sltu $[[T3:[0-9]+]], $[[T1]], $7
+ ; MMR3: addu16 $[[T4:[0-9]+]], $6, $[[T3]]
+ ; MMR3: sltu $[[T5:[0-9]+]], $[[T4]], $6
+ ; MMR3: movz $[[T5]], $[[T3]], $[[T2]]
+ ; MMR3: addu16 $[[T6:[0-9]+]], $5, $[[T5]]
+ ; MMR3: sltu $[[T7:[0-9]+]], $[[T6]], $5
+ ; MMR3: addu16 $2, $4, $[[T7]]
+
+ ; MMR6: move $[[T1:[0-9]+]], $7
+ ; MMR6: addius5 $[[T1]], 3
+ ; MMR6: sltu $[[T2:[0-9]+]], $[[T1]], $7
+ ; MMR6: xori $[[T3:[0-9]+]], $[[T2]], 1
+ ; MMR6: selnez $[[T4:[0-9]+]], $[[T2]], $[[T3]]
+ ; MMR6: addu16 $[[T5:[0-9]+]], $6, $[[T2]]
+ ; MMR6: sltu $[[T6:[0-9]+]], $[[T5]], $6
+ ; MMR6: seleqz $[[T7:[0-9]+]], $[[T6]], $[[T3]]
+ ; MMR6: or $[[T8:[0-9]+]], $[[T4]], $[[T7]]
+ ; MMR6: addu16 $[[T9:[0-9]+]], $5, $[[T8]]
+ ; MMR6: sltu $[[T10:[0-9]+]], $[[T9]], $5
+ ; MMR6: addu16 $[[T11:[0-9]+]], $4, $[[T10]]
+ ; MMR6: move $4, $[[T5]]
+ ; MMR6: move $5, $[[T1]]
; MM64: daddiu $[[T0:[0-9]+]], $5, 3
- ; MM64: daddiu $[[T1:[0-9]+]], $zero, 3
- ; MM64: sltu $[[T1]], $[[T0]], $[[T1]]
- ; MM64: daddu $2, $4, $[[T1]]
+ ; MM64: sltu $[[T1:[0-9]+]], $[[T0]], $5
+ ; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32
+ ; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+ ; MM64: daddu $2, $4, $[[T3]]
%r = add i128 3, %a
ret i128 %r
diff --git a/test/CodeGen/Mips/llvm-ir/sub.ll b/test/CodeGen/Mips/llvm-ir/sub.ll
index a730063c552f..655addb10a64 100644
--- a/test/CodeGen/Mips/llvm-ir/sub.ll
+++ b/test/CodeGen/Mips/llvm-ir/sub.ll
@@ -1,5 +1,5 @@
; RUN: llc < %s -march=mips -mcpu=mips2 | FileCheck %s \
-; RUN: -check-prefixes=NOT-R2-R6,GP32,GP32-NOT-MM,NOT-MM
+; RUN: -check-prefixes=NOT-R2-R6,GP32,GP32-NOT-MM,NOT-MM,PRE4
; RUN: llc < %s -march=mips -mcpu=mips32 | FileCheck %s \
; RUN: -check-prefixes=NOT-R2-R6,GP32,GP32-NOT-MM,NOT-MM
; RUN: llc < %s -march=mips -mcpu=mips32r2 | FileCheck %s \
@@ -11,25 +11,25 @@
; RUN: llc < %s -march=mips -mcpu=mips32r6 | FileCheck %s \
; RUN: -check-prefixes=R2-R6,GP32,GP32-NOT-MM,NOT-MM
; RUN: llc < %s -march=mips -mcpu=mips32r3 -mattr=+micromips -verify-machineinstrs | FileCheck %s \
-; RUN: -check-prefixes=GP32-MM,GP32,MM
+; RUN: -check-prefixes=GP32-MM,GP32,MM32,MMR3
; RUN: llc < %s -march=mips -mcpu=mips32r6 -mattr=+micromips | FileCheck %s \
-; RUN: -check-prefixes=GP32-MM,GP32,MM
+; RUN: -check-prefixes=GP32-MM,GP32,MM32,MMR6
; RUN: llc < %s -march=mips64 -mcpu=mips3 | FileCheck %s \
-; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM
+; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM,GP64-NOT-R2
; RUN: llc < %s -march=mips64 -mcpu=mips4 | FileCheck %s \
-; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM
+; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM,GP64-NOT-R2
; RUN: llc < %s -march=mips64 -mcpu=mips64 | FileCheck %s \
-; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM
+; RUN: -check-prefixes=NOT-R2-R6,GP64,NOT-MM,GP64-NOT-R2
; RUN: llc < %s -march=mips64 -mcpu=mips64r2 | FileCheck %s \
-; RUN: -check-prefixes=R2-R6,GP64,NOT-MM
+; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2
; RUN: llc < %s -march=mips64 -mcpu=mips64r3 | FileCheck %s \
-; RUN: -check-prefixes=R2-R6,GP64,NOT-MM
+; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2
; RUN: llc < %s -march=mips64 -mcpu=mips64r5 | FileCheck %s \
-; RUN: -check-prefixes=R2-R6,GP64,NOT-MM
+; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2
; RUN: llc < %s -march=mips64 -mcpu=mips64r6 | FileCheck %s \
-; RUN: -check-prefixes=R2-R6,GP64,NOT-MM
+; RUN: -check-prefixes=R2-R6,GP64,NOT-MM,GP64-R2
; RUN: llc < %s -march=mips64 -mcpu=mips64r6 -mattr=+micromips | FileCheck %s \
-; RUN: -check-prefixes=GP64,MM
+; RUN: -check-prefixes=GP64,MM64
define signext i1 @sub_i1(i1 signext %a, i1 signext %b) {
entry:
@@ -100,10 +100,15 @@ define signext i64 @sub_i64(i64 signext %a, i64 signext %b) {
entry:
; ALL-LABEL: sub_i64:
- ; GP32-NOT-MM subu $3, $5, $7
- ; GP32: sltu $[[T0:[0-9]+]], $5, $7
- ; GP32: addu $[[T1:[0-9]+]], $[[T0]], $6
- ; GP32: subu $2, $4, $[[T1]]
+ ; GP32-NOT-MM: sltu $[[T0:[0-9]+]], $5, $7
+ ; GP32-NOT-MM: subu $2, $4, $6
+ ; GP32-NOT-MM: subu $2, $2, $[[T0]]
+ ; GP32-NOT-MM: subu $3, $5, $7
+
+ ; MM32: sltu $[[T0:[0-9]+]], $5, $7
+ ; MM32: subu16 $3, $4, $6
+ ; MM32: subu16 $2, $3, $[[T0]]
+ ; MM32: subu16 $3, $5, $7
; GP64: dsubu $2, $4, $5
@@ -115,42 +120,109 @@ define signext i128 @sub_i128(i128 signext %a, i128 signext %b) {
entry:
; ALL-LABEL: sub_i128:
- ; GP32-NOT-MM: lw $[[T0:[0-9]+]], 20($sp)
- ; GP32-NOT-MM: sltu $[[T1:[0-9]+]], $5, $[[T0]]
- ; GP32-NOT-MM: lw $[[T2:[0-9]+]], 16($sp)
- ; GP32-NOT-MM: addu $[[T3:[0-9]+]], $[[T1]], $[[T2]]
- ; GP32-NOT-MM: lw $[[T4:[0-9]+]], 24($sp)
- ; GP32-NOT-MM: lw $[[T5:[0-9]+]], 28($sp)
- ; GP32-NOT-MM: subu $[[T6:[0-9]+]], $7, $[[T5]]
- ; GP32-NOT-MM: subu $2, $4, $[[T3]]
- ; GP32-NOT-MM: sltu $[[T8:[0-9]+]], $6, $[[T4]]
- ; GP32-NOT-MM: addu $[[T9:[0-9]+]], $[[T8]], $[[T0]]
- ; GP32-NOT-MM: subu $3, $5, $[[T9]]
- ; GP32-NOT-MM: sltu $[[T10:[0-9]+]], $7, $[[T5]]
- ; GP32-NOT-MM: addu $[[T11:[0-9]+]], $[[T10]], $[[T4]]
- ; GP32-NOT-MM: subu $4, $6, $[[T11]]
- ; GP32-NOT-MM: move $5, $[[T6]]
-
- ; GP32-MM: lw $[[T0:[0-9]+]], 20($sp)
- ; GP32-MM: sltu $[[T1:[0-9]+]], $[[T2:[0-9]+]], $[[T0]]
- ; GP32-MM: lw $[[T3:[0-9]+]], 16($sp)
- ; GP32-MM: addu $[[T3]], $[[T1]], $[[T3]]
- ; GP32-MM: lw $[[T4:[0-9]+]], 24($sp)
- ; GP32-MM: lw $[[T5:[0-9]+]], 28($sp)
- ; GP32-MM: subu $[[T1]], $7, $[[T5]]
- ; GP32-MM: subu16 $[[T3]], $[[T6:[0-9]+]], $[[T3]]
- ; GP32-MM: sltu $[[T6]], $6, $[[T4]]
- ; GP32-MM: addu16 $[[T0]], $[[T6]], $[[T0]]
- ; GP32-MM: subu16 $[[T0]], $5, $[[T0]]
- ; GP32-MM: sltu $[[T6]], $7, $[[T5]]
- ; GP32-MM: addu $[[T6]], $[[T6]], $[[T4]]
- ; GP32-MM: subu16 $[[T6]], $6, $[[T6]]
- ; GP32-MM: move $[[T2]], $[[T1]]
-
- ; GP64: dsubu $3, $5, $7
- ; GP64: sltu $[[T0:[0-9]+]], $5, $7
- ; GP64: daddu $[[T1:[0-9]+]], $[[T0]], $6
- ; GP64: dsubu $2, $4, $[[T1]]
+; PRE4: lw $[[T0:[0-9]+]], 24($sp)
+; PRE4: lw $[[T1:[0-9]+]], 28($sp)
+; PRE4: sltu $[[T2:[0-9]+]], $7, $[[T1]]
+; PRE4: xor $[[T3:[0-9]+]], $6, $[[T0]]
+; PRE4: sltiu $[[T4:[0-9]+]], $[[T3]], 1
+; PRE4: bnez $[[T4]]
+; PRE4: move $[[T5:[0-9]+]], $[[T2]]
+; PRE4: sltu $[[T5]], $6, $[[T0]]
+
+; PRE4: lw $[[T6:[0-9]+]], 20($sp)
+; PRE4: subu $[[T7:[0-9]+]], $5, $[[T6]]
+; PRE4: subu $[[T8:[0-9]+]], $[[T7]], $[[T5]]
+; PRE4: sltu $[[T9:[0-9]+]], $[[T7]], $[[T5]]
+; PRE4: sltu $[[T10:[0-9]+]], $5, $[[T6]]
+; PRE4: lw $[[T11:[0-9]+]], 16($sp)
+; PRE4: subu $[[T12:[0-9]+]], $4, $[[T11]]
+; PRE4: subu $[[T13:[0-9]+]], $[[T12]], $[[T10]]
+; PRE4: subu $[[T14:[0-9]+]], $[[T13]], $[[T9]]
+; PRE4: subu $[[T15:[0-9]+]], $6, $[[T0]]
+; PRE4: subu $[[T16:[0-9]+]], $[[T15]], $[[T2]]
+; PRE4: subu $5, $7, $[[T1]]
+
+; MMR3: lw $[[T1:[0-9]+]], 48($sp)
+; MMR3: sltu $[[T2:[0-9]+]], $6, $[[T1]]
+; MMR3: xor $[[T3:[0-9]+]], $6, $[[T1]]
+; MMR3: lw $[[T4:[0-9]+]], 52($sp)
+; MMR3: sltu $[[T5:[0-9]+]], $7, $[[T4]]
+; MMR3: movz $[[T6:[0-9]+]], $[[T5]], $[[T3]]
+; MMR3: lw $[[T7:[0-8]+]], 44($sp)
+; MMR3: subu16 $[[T8:[0-9]+]], $5, $[[T7]]
+; MMR3: subu16 $[[T9:[0-9]+]], $[[T8]], $[[T6]]
+; MMR3: sltu $[[T10:[0-9]+]], $[[T8]], $[[T2]]
+; MMR3: sltu $[[T11:[0-9]+]], $5, $[[T7]]
+; MMR3: lw $[[T12:[0-9]+]], 40($sp)
+; MMR3: lw $[[T13:[0-9]+]], 12($sp)
+; MMR3: subu16 $[[T14:[0-9]+]], $[[T13]], $[[T12]]
+; MMR3: subu16 $[[T15:[0-9]+]], $[[T14]], $[[T11]]
+; MMR3: subu16 $[[T16:[0-9]+]], $[[T15]], $[[T10]]
+; MMR3: subu16 $[[T17:[0-9]+]], $6, $[[T1]]
+; MMR3: subu16 $[[T18:[0-9]+]], $[[T17]], $7
+; MMR3: lw $[[T19:[0-9]+]], 8($sp)
+; MMR3: lw $[[T20:[0-9]+]], 0($sp)
+; MMR3: subu16 $5, $[[T19]], $[[T20]]
+
+; MMR6: move $[[T0:[0-9]+]], $7
+; MMR6: sw $[[T0]], 8($sp)
+; MMR6: move $[[T1:[0-9]+]], $5
+; MMR6: sw $4, 12($sp)
+; MMR6: lw $[[T2:[0-9]+]], 48($sp)
+; MMR6: sltu $[[T3:[0-9]+]], $6, $[[T2]]
+; MMR6: xor $[[T4:[0-9]+]], $6, $[[T2]]
+; MMR6: sltiu $[[T5:[0-9]+]], $[[T4]], 1
+; MMR6: seleqz $[[T6:[0-9]+]], $[[T3]], $[[T5]]
+; MMR6: lw $[[T7:[0-9]+]], 52($sp)
+; MMR6: sltu $[[T8:[0-9]+]], $[[T0]], $[[T7]]
+; MMR6: selnez $[[T9:[0-9]+]], $[[T8]], $[[T5]]
+; MMR6: or $[[T10:[0-9]+]], $[[T9]], $[[T6]]
+; MMR6: lw $[[T11:[0-9]+]], 44($sp)
+; MMR6: subu16 $[[T12:[0-9]+]], $[[T1]], $[[T11]]
+; MMR6: subu16 $[[T13:[0-9]+]], $[[T12]], $[[T7]]
+; MMR6: sltu $[[T16:[0-9]+]], $[[T12]], $[[T7]]
+; MMR6: sltu $[[T17:[0-9]+]], $[[T1]], $[[T11]]
+; MMR6: lw $[[T18:[0-9]+]], 40($sp)
+; MMR6: lw $[[T19:[0-9]+]], 12($sp)
+; MMR6: subu16 $[[T20:[0-9]+]], $[[T19]], $[[T18]]
+; MMR6: subu16 $[[T21:[0-9]+]], $[[T20]], $[[T17]]
+; MMR6: subu16 $[[T22:[0-9]+]], $[[T21]], $[[T16]]
+; MMR6: subu16 $[[T23:[0-9]+]], $6, $[[T2]]
+; MMR6: subu16 $4, $[[T23]], $5
+; MMR6: lw $[[T24:[0-9]+]], 8($sp)
+; MMR6: lw $[[T25:[0-9]+]], 0($sp)
+; MMR6: subu16 $5, $[[T24]], $[[T25]]
+; MMR6: lw $3, 4($sp)
+
+; FIXME: The sltu, dsll, dsrl pattern here occurs when an i32 is zero
+; extended to 64 bits. Fortunately slt(i)(u) actually gives an i1.
+; These should be combined away.
+
+; GP64-NOT-R2: dsubu $1, $4, $6
+; GP64-NOT-R2: sltu $[[T0:[0-9]+]], $5, $7
+; GP64-NOT-R2: dsll $[[T1:[0-9]+]], $[[T0]], 32
+; GP64-NOT-R2: dsrl $[[T2:[0-9]+]], $[[T1]], 32
+; GP64-NOT-R2: dsubu $2, $1, $[[T2]]
+; GP64-NOT-R2: dsubu $3, $5, $7
+
+; FIXME: Likewise for the sltu, dext here.
+
+; GP64-R2: dsubu $1, $4, $6
+; GP64-R2: sltu $[[T0:[0-9]+]], $5, $7
+; GP64-R2: dext $[[T1:[0-9]+]], $[[T0]], 0, 32
+; GP64-R2: dsubu $2, $1, $[[T1]]
+; GP64-R2: dsubu $3, $5, $7
+
+; FIXME: Again, redundant sign extension. Also, microMIPSR6 has the
+; dext instruction which should be used here.
+
+; MM64: dsubu $[[T0:[0-9]+]], $4, $6
+; MM64: sltu $[[T1:[0-9]+]], $5, $7
+; MM64: dsll $[[T2:[0-9]+]], $[[T1]], 32
+; MM64: dsrl $[[T3:[0-9]+]], $[[T2]], 32
+; MM64: dsubu $2, $[[T0]], $[[T3]]
+; MM64: dsubu $3, $5, $7
+; MM64: jr $ra
%r = sub i128 %a, %b
ret i128 %r
diff --git a/test/CodeGen/Mips/longbranch.ll b/test/CodeGen/Mips/longbranch.ll
index 11bc6d390319..c616089c6df0 100644
--- a/test/CodeGen/Mips/longbranch.ll
+++ b/test/CodeGen/Mips/longbranch.ll
@@ -1,17 +1,17 @@
-; RUN: llc -march=mipsel -relocation-model=pic < %s | FileCheck %s
-; RUN: llc -march=mipsel -force-mips-long-branch -O3 -relocation-model=pic < %s \
+; RUN: llc -march=mipsel -relocation-model=pic < %s -verify-machineinstrs | FileCheck %s
+; RUN: llc -march=mipsel -force-mips-long-branch -O3 -relocation-model=pic < %s -verify-machineinstrs \
; RUN: | FileCheck %s -check-prefix=O32
; RUN: llc -march=mipsel -mcpu=mips32r6 -force-mips-long-branch -O3 \
-; RUN: -relocation-model=pic -asm-show-inst < %s | FileCheck %s -check-prefix=O32-R6
+; RUN: -relocation-model=pic -asm-show-inst < %s -verify-machineinstrs | FileCheck %s -check-prefix=O32-R6
; RUN: llc -march=mips64el -mcpu=mips4 -target-abi=n64 -force-mips-long-branch -O3 -relocation-model=pic \
-; RUN: < %s | FileCheck %s -check-prefix=N64
+; RUN: < %s -verify-machineinstrs | FileCheck %s -check-prefix=N64
; RUN: llc -march=mips64el -mcpu=mips64 -target-abi=n64 -force-mips-long-branch -O3 -relocation-model=pic \
-; RUN: < %s | FileCheck %s -check-prefix=N64
+; RUN: < %s -verify-machineinstrs | FileCheck %s -check-prefix=N64
; RUN: llc -march=mips64el -mcpu=mips64r6 -target-abi=n64 -force-mips-long-branch -O3 \
-; RUN: -relocation-model=pic -asm-show-inst < %s | FileCheck %s -check-prefix=N64-R6
+; RUN: -relocation-model=pic -asm-show-inst < %s -verify-machineinstrs | FileCheck %s -check-prefix=N64-R6
; RUN: llc -march=mipsel -mcpu=mips32r2 -mattr=micromips \
-; RUN: -force-mips-long-branch -O3 -relocation-model=pic < %s | FileCheck %s -check-prefix=MICROMIPS
-; RUN: llc -mtriple=mipsel-none-nacl -force-mips-long-branch -O3 -relocation-model=pic < %s \
+; RUN: -force-mips-long-branch -O3 -relocation-model=pic < %s -verify-machineinstrs | FileCheck %s -check-prefix=MICROMIPS
+; RUN: llc -mtriple=mipsel-none-nacl -force-mips-long-branch -O3 -relocation-model=pic < %s -verify-machineinstrs \
; RUN: | FileCheck %s -check-prefix=NACL
@@ -59,9 +59,9 @@ end:
; Check for long branch expansion:
; O32: addiu $sp, $sp, -8
; O32-NEXT: sw $ra, 0($sp)
-; O32-NEXT: lui $1, %hi(($[[BB2:BB[0-9_]+]])-($[[BB1:BB[0-9_]+]]))
+; O32-NEXT: lui $1, %hi(($BB0_[[BB2:[0-9]+]])-($[[BB1:BB[0-9_]+]]))
; O32-NEXT: bal $[[BB1]]
-; O32-NEXT: addiu $1, $1, %lo(($[[BB2]])-($[[BB1]]))
+; O32-NEXT: addiu $1, $1, %lo(($BB0_[[BB2]])-($[[BB1]]))
; O32-NEXT: $[[BB1]]:
; O32-NEXT: addu $1, $ra, $1
; O32-NEXT: lw $ra, 0($sp)
@@ -72,7 +72,7 @@ end:
; O32: lw $[[R1:[0-9]+]], %got(x)($[[GP]])
; O32: addiu $[[R2:[0-9]+]], $zero, 1
; O32: sw $[[R2]], 0($[[R1]])
-; O32: $[[BB2]]:
+; O32: # BB#[[BB2]]:
; O32: jr $ra
; O32: nop
@@ -90,10 +90,10 @@ end:
; Check for long branch expansion:
; N64: daddiu $sp, $sp, -16
; N64-NEXT: sd $ra, 0($sp)
-; N64-NEXT: daddiu $1, $zero, %hi([[BB2:\.LBB[0-9_]+]]-[[BB1:\.LBB[0-9_]+]])
+; N64-NEXT: daddiu $1, $zero, %hi(.LBB0_[[BB2:[0-9_]+]]-[[BB1:\.LBB[0-9_]+]])
; N64-NEXT: dsll $1, $1, 16
; N64-NEXT: bal [[BB1]]
-; N64-NEXT: daddiu $1, $1, %lo([[BB2]]-[[BB1]])
+; N64-NEXT: daddiu $1, $1, %lo(.LBB0_[[BB2]]-[[BB1]])
; N64-NEXT: [[BB1]]:
; N64-NEXT: daddu $1, $ra, $1
; N64-NEXT: ld $ra, 0($sp)
@@ -105,7 +105,7 @@ end:
; N64: addiu $[[R3:[0-9]+]], $zero, 1
; N64: ld $[[R2:[0-9]+]], %got_disp(x)($[[GP]])
; N64: sw $[[R3]], 0($[[R2]])
-; N64: [[BB2]]:
+; N64: # BB#[[BB2]]:
; N64: jr $ra
; N64: nop
@@ -125,9 +125,9 @@ end:
; Check for long branch expansion:
; MICROMIPS: addiu $sp, $sp, -8
; MICROMIPS-NEXT: sw $ra, 0($sp)
-; MICROMIPS-NEXT: lui $1, %hi(($[[BB2:BB[0-9_]+]])-($[[BB1:BB[0-9_]+]]))
+; MICROMIPS-NEXT: lui $1, %hi(($BB0_[[BB2:[0-9]+]])-($[[BB1:BB[0-9_]+]]))
; MICROMIPS-NEXT: bal $[[BB1]]
-; MICROMIPS-NEXT: addiu $1, $1, %lo(($[[BB2]])-($[[BB1]]))
+; MICROMIPS-NEXT: addiu $1, $1, %lo(($BB0_[[BB2]])-($[[BB1]]))
; MICROMIPS-NEXT: $[[BB1]]:
; MICROMIPS-NEXT: addu $1, $ra, $1
; MICROMIPS-NEXT: lw $ra, 0($sp)
@@ -138,7 +138,7 @@ end:
; MICROMIPS: lw $[[R1:[0-9]+]], %got(x)($[[GP]])
; MICROMIPS: li16 $[[R2:[0-9]+]], 1
; MICROMIPS: sw16 $[[R2]], 0($[[R1]])
-; MICROMIPS: $[[BB2]]:
+; MICROMIPS: # BB#[[BB2]]:
; MICROMIPS: jrc $ra
@@ -154,9 +154,9 @@ end:
; Check for long branch expansion:
; NACL: addiu $sp, $sp, -8
; NACL-NEXT: sw $ra, 0($sp)
-; NACL-NEXT: lui $1, %hi(($[[BB2:BB[0-9_]+]])-($[[BB1:BB[0-9_]+]]))
+; NACL-NEXT: lui $1, %hi(($BB0_[[BB2:[0-9]+]])-($[[BB1:BB[0-9_]+]]))
; NACL-NEXT: bal $[[BB1]]
-; NACL-NEXT: addiu $1, $1, %lo(($[[BB2]])-($[[BB1]]))
+; NACL-NEXT: addiu $1, $1, %lo(($BB0_[[BB2]])-($[[BB1]]))
; NACL-NEXT: $[[BB1]]:
; NACL-NEXT: addu $1, $ra, $1
; NACL-NEXT: lw $ra, 0($sp)
@@ -169,7 +169,7 @@ end:
; NACL: addiu $[[R2:[0-9]+]], $zero, 1
; NACL: sw $[[R2]], 0($[[R1]])
; NACL: .p2align 4
-; NACL-NEXT: $[[BB2]]:
+; NACL-NEXT: # BB#[[BB2]]:
; NACL: jr $ra
; NACL: nop
}
diff --git a/test/CodeGen/Mips/madd-msub.ll b/test/CodeGen/Mips/madd-msub.ll
index 7baba005a072..3e1a2e8b9708 100644
--- a/test/CodeGen/Mips/madd-msub.ll
+++ b/test/CodeGen/Mips/madd-msub.ll
@@ -25,11 +25,11 @@
; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6
-; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6
-; 32R6-DAG: sra $[[T3:[0-9]+]], $6, 31
-; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $[[T3]]
-; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}}
-; 32R6-DAG: addu $2, $[[T5]], $[[T4]]
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]]
+; 32R6-DAG: muh $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: sra $[[T4:[0-9]+]], $6, 31
+; 32R6-DAG: addu $[[T5:[0-9]+]], $[[T3]], $[[T4]]
+; 32R6-DAG: addu $2, $[[T5]], $[[T2]]
; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
@@ -71,7 +71,7 @@ entry:
; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $6
-; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $6
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $[[T0]]
; FIXME: There's a redundant move here. We should remove it
; 32R6-DAG: muhu $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}}
; 32R6-DAG: addu $2, $[[T3]], $[[T2]]
@@ -109,10 +109,10 @@ entry:
; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
; 32R6-DAG: addu $[[T1:[0-9]+]], $[[T0]], $7
-; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $7
-; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T2]], $6
-; 32R6-DAG: muh $[[T5:[0-9]+]], ${{[45]}}, ${{[45]}}
-; 32R6-DAG: addu $2, $[[T5]], $[[T4]]
+; 32R6-DAG: sltu $[[T2:[0-9]+]], $[[T1]], $1
+; 32R6-DAG: muh $[[T3:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T3]], $6
+; 32R6-DAG: addu $2, $[[T4]], $[[T2]]
; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
@@ -134,6 +134,17 @@ entry:
ret i64 %add
}
+; ALL-LABEL: madd4
+; ALL-NOT: madd ${{[0-9]+}}, ${{[0-9]+}}
+
+define i32 @madd4(i32 %a, i32 %b, i32 %c) {
+entry:
+ %mul = mul nsw i32 %a, %b
+ %add = add nsw i32 %c, %mul
+
+ ret i32 %add
+}
+
; ALL-LABEL: msub1:
; 32-DAG: sra $[[T0:[0-9]+]], $6, 31
@@ -148,13 +159,13 @@ entry:
; DSP-DAG: mfhi $2, $[[AC]]
; DSP-DAG: mflo $3, $[[AC]]
-; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
-; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}}
-; 32R6-DAG: sltu $[[T3:[0-9]+]], $6, $[[T1]]
-; 32R6-DAG: addu $[[T4:[0-9]+]], $[[T3]], $[[T0]]
-; 32R6-DAG: sra $[[T5:[0-9]+]], $6, 31
-; 32R6-DAG: subu $2, $[[T5]], $[[T4]]
-; 32R6-DAG: subu $3, $6, $[[T1]]
+; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: sltu $[[T1:[0-9]+]], $6, $[[T0]]
+; 32R6-DAG: muh $[[T2:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: sra $[[T3:[0-9]+]], $6, 31
+; 32R6-DAG: subu $[[T4:[0-9]+]], $[[T3]], $[[T2]]
+; 32R6-DAG: subu $2, $[[T4]], $[[T1]]
+; 32R6-DAG: subu $3, $6, $[[T0]]
; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
@@ -194,13 +205,12 @@ entry:
; DSP-DAG: mfhi $2, $[[AC]]
; DSP-DAG: mflo $3, $[[AC]]
-; 32R6-DAG: muhu $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
-; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}}
-
-; 32R6-DAG: sltu $[[T2:[0-9]+]], $6, $[[T1]]
-; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]]
-; 32R6-DAG: negu $2, $[[T3]]
-; 32R6-DAG: subu $3, $6, $[[T1]]
+; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: sltu $[[T1:[0-9]+]], $6, $[[T0]]
+; 32R6-DAG: muhu $[[T2:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: negu $[[T3:[0-9]+]], $[[T2]]
+; 32R6-DAG: subu $2, $[[T3]], $[[T1]]
+; 32R6-DAG: subu $3, $6, $[[T0]]
; 64-DAG: d[[m:m]]ult $5, $4
; 64-DAG: [[m]]flo $[[T0:[0-9]+]]
@@ -234,12 +244,12 @@ entry:
; DSP-DAG: mfhi $2, $[[AC]]
; DSP-DAG: mflo $3, $[[AC]]
-; 32R6-DAG: muh $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
-; 32R6-DAG: mul $[[T1:[0-9]+]], ${{[45]}}, ${{[45]}}
-; 32R6-DAG: sltu $[[T2:[0-9]+]], $7, $[[T1]]
-; 32R6-DAG: addu $[[T3:[0-9]+]], $[[T2]], $[[T0]]
-; 32R6-DAG: subu $2, $6, $[[T3]]
-; 32R6-DAG: subu $3, $7, $[[T1]]
+; 32R6-DAG: mul $[[T0:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: sltu $[[T1:[0-9]+]], $7, $[[T0]]
+; 32R6-DAG: muh $[[T2:[0-9]+]], ${{[45]}}, ${{[45]}}
+; 32R6-DAG: subu $[[T3:[0-9]+]], $6, $[[T2]]
+; 32R6-DAG: subu $2, $[[T3]], $[[T1]]
+; 32R6-DAG: subu $3, $7, $[[T0]]
; 64-DAG: sll $[[T0:[0-9]+]], $4, 0
; 64-DAG: sll $[[T1:[0-9]+]], $5, 0
@@ -260,3 +270,14 @@ entry:
%sub = sub nsw i64 %c, %mul
ret i64 %sub
}
+
+; ALL-LABEL: msub4
+; ALL-NOT: msub ${{[0-9]+}}, ${{[0-9]+}}
+
+define i32 @msub4(i32 %a, i32 %b, i32 %c) {
+entry:
+ %mul = mul nsw i32 %a, %b
+ %sub = sub nsw i32 %c, %mul
+
+ ret i32 %sub
+}
diff --git a/test/CodeGen/PowerPC/atomic-2.ll b/test/CodeGen/PowerPC/atomic-2.ll
index 2039c1f57f17..f402cb78bd18 100644
--- a/test/CodeGen/PowerPC/atomic-2.ll
+++ b/test/CodeGen/PowerPC/atomic-2.ll
@@ -109,7 +109,7 @@ entry:
%tmp = load atomic i64, i64* %mem acquire, align 64
; CHECK-NOT: ldarx
; CHECK: ld [[VAL:r[0-9]+]]
-; CHECK: cmpw [[CR:cr[0-9]+]], [[VAL]], [[VAL]]
+; CHECK: cmpd [[CR:cr[0-9]+]], [[VAL]], [[VAL]]
; CHECK: bne- [[CR]], .+4
; CHECK: isync
ret i64 %tmp
diff --git a/test/CodeGen/PowerPC/atomics-constant.ll b/test/CodeGen/PowerPC/atomics-constant.ll
index a92ca813af85..77825c608a3b 100644
--- a/test/CodeGen/PowerPC/atomics-constant.ll
+++ b/test/CodeGen/PowerPC/atomics-constant.ll
@@ -11,7 +11,7 @@ define i64 @foo() {
; CHECK-NEXT: addis 3, 2, .LC0@toc@ha
; CHECK-NEXT: li 4, 0
; CHECK-NEXT: ld 3, .LC0@toc@l(3)
-; CHECK-NEXT: cmpw 7, 4, 4
+; CHECK-NEXT: cmpd 7, 4, 4
; CHECK-NEXT: ld 3, 0(3)
; CHECK-NEXT: bne- 7, .+4
; CHECK-NEXT: isync
diff --git a/test/CodeGen/PowerPC/atomics-regression.ll b/test/CodeGen/PowerPC/atomics-regression.ll
index 054d3a4146b0..d57b3a203791 100644
--- a/test/CodeGen/PowerPC/atomics-regression.ll
+++ b/test/CodeGen/PowerPC/atomics-regression.ll
@@ -23,7 +23,7 @@ define i8 @test2(i8* %ptr) {
; PPC64LE-LABEL: test2:
; PPC64LE: # BB#0:
; PPC64LE-NEXT: lbz 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -37,7 +37,7 @@ define i8 @test3(i8* %ptr) {
; PPC64LE-NEXT: sync
; PPC64LE-NEXT: ori 2, 2, 0
; PPC64LE-NEXT: lbz 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -67,7 +67,7 @@ define i16 @test6(i16* %ptr) {
; PPC64LE-LABEL: test6:
; PPC64LE: # BB#0:
; PPC64LE-NEXT: lhz 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -81,7 +81,7 @@ define i16 @test7(i16* %ptr) {
; PPC64LE-NEXT: sync
; PPC64LE-NEXT: ori 2, 2, 0
; PPC64LE-NEXT: lhz 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -111,7 +111,7 @@ define i32 @test10(i32* %ptr) {
; PPC64LE-LABEL: test10:
; PPC64LE: # BB#0:
; PPC64LE-NEXT: lwz 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -125,7 +125,7 @@ define i32 @test11(i32* %ptr) {
; PPC64LE-NEXT: sync
; PPC64LE-NEXT: ori 2, 2, 0
; PPC64LE-NEXT: lwz 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -155,7 +155,7 @@ define i64 @test14(i64* %ptr) {
; PPC64LE-LABEL: test14:
; PPC64LE: # BB#0:
; PPC64LE-NEXT: ld 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -169,7 +169,7 @@ define i64 @test15(i64* %ptr) {
; PPC64LE-NEXT: sync
; PPC64LE-NEXT: ori 2, 2, 0
; PPC64LE-NEXT: ld 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: blr
@@ -9566,7 +9566,7 @@ define i32 @test_ordering0(i32* %ptr1, i32* %ptr2) {
; PPC64LE-LABEL: test_ordering0:
; PPC64LE: # BB#0:
; PPC64LE-NEXT: lwz 4, 0(3)
-; PPC64LE-NEXT: cmpw 7, 4, 4
+; PPC64LE-NEXT: cmpd 7, 4, 4
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: lwz 3, 0(3)
@@ -9583,7 +9583,7 @@ define i32 @test_ordering1(i32* %ptr1, i32 %val1, i32* %ptr2) {
; PPC64LE-LABEL: test_ordering1:
; PPC64LE: # BB#0:
; PPC64LE-NEXT: lwz 3, 0(3)
-; PPC64LE-NEXT: cmpw 7, 3, 3
+; PPC64LE-NEXT: cmpd 7, 3, 3
; PPC64LE-NEXT: bne- 7, .+4
; PPC64LE-NEXT: isync
; PPC64LE-NEXT: stw 4, 0(5)
diff --git a/test/CodeGen/PowerPC/licm-tocReg.ll b/test/CodeGen/PowerPC/licm-tocReg.ll
new file mode 100644
index 000000000000..ecdfcba6e3b7
--- /dev/null
+++ b/test/CodeGen/PowerPC/licm-tocReg.ll
@@ -0,0 +1,110 @@
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s | FileCheck %s
+
+; The instructions ADDIStocHA/LDtocL are used to calculate the address of
+; globals. The ones that are in bb.3.if.end could not be hoisted by Machine
+; LICM due to BCTRL_LDinto_toc in bb2.if.then. This call causes the compiler
+; to insert a save TOC to stack before the call and load into X2 to restore TOC
+; after. By communicating to Machine LICM that X2 is guaranteed to have the
+; same value before and after BCTRL_LDinto_toc, these instructions can be
+; hoisted out of bb.3.if.end to outside of the loop.
+
+; Pre Machine LICM MIR
+;
+;body:
+; bb.0.entry:
+; successors: %bb.2.if.then(0x40000000), %bb.3.if.end(0x40000000)
+; liveins: %x3
+;
+; %4 = COPY %x3
+; %5 = ADDIStocHA %x2, @ga
+; %6 = LDtocL @ga, killed %5 :: (load 8 from got)
+; %7 = LWZ 0, %6 :: (volatile dereferenceable load 4 from @ga)
+; %8 = ADDIStocHA %x2, @gb
+; %9 = LDtocL @gb, killed %8 :: (load 8 from got)
+; %10 = LWZ 0, killed %9 :: (volatile dereferenceable load 4 from @gb)
+; %0 = LWZ 0, %6 :: (volatile dereferenceable load 4 from @ga)
+; %11 = CMPW killed %7, killed %10
+; BCC 44, killed %11, %bb.2.if.then
+; B %bb.3.if.end
+;
+; bb.2.if.then:
+; %1 = PHI %0, %bb.0.entry, %3, %bb.3.if.end
+; ADJCALLSTACKDOWN 32, 0, implicit-def dead %r1, implicit %r1
+; %20 = COPY %x2
+; STD %20, 24, %x1 :: (store 8 into stack + 24)
+; %21 = EXTSW_32_64 %1
+; %x3 = COPY %21
+; %x12 = COPY %4
+; MTCTR8 %4, implicit-def %ctr8
+; BCTRL8_LDinto_toc 24, %x1, csr_svr464_altivec, implicit-def dead %lr8, implicit-def dead %x2, implicit %ctr8, implicit %rm, implicit %x3, implicit %x12, implicit %x2, implicit-def %r1, implicit-def %x3
+; ADJCALLSTACKUP 32, 0, implicit-def dead %r1, implicit %r1
+; %22 = COPY %x3
+; %x3 = COPY %22
+; BLR8 implicit %lr8, implicit %rm, implicit %x3
+;
+; bb.3.if.end:
+; successors: %bb.2.if.then(0x04000000), %bb.3.if.end(0x7c000000)
+;
+; %2 = PHI %0, %bb.0.entry, %3, %bb.3.if.end
+; %12 = ADDI %2, 1
+; %13 = ADDIStocHA %x2, @ga
+; %14 = LDtocL @ga, killed %13 :: (load 8 from got)
+; STW killed %12, 0, %14 :: (volatile store 4 into @ga)
+; %15 = LWZ 0, %14 :: (volatile dereferenceable load 4 from @ga)
+; %16 = ADDIStocHA %x2, @gb
+; %17 = LDtocL @gb, killed %16 :: (load 8 from got)
+; %18 = LWZ 0, killed %17 :: (volatile dereferenceable load 4 from @gb)
+; %3 = LWZ 0, %14 :: (volatile dereferenceable load 4 from @ga)
+; %19 = CMPW killed %15, killed %18
+; BCC 44, killed %19, %bb.2.if.then
+; B %bb.3.if.end
+
+@ga = external global i32, align 4
+@gb = external global i32, align 4
+
+; Function Attrs: nounwind
+define signext i32 @test(i32 (i32)* nocapture %FP) local_unnamed_addr #0 {
+; CHECK-LABEL: test:
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: addis 4, 2, .LC0@toc@ha
+; CHECK-NEXT: addis 5, 2, .LC1@toc@ha
+; CHECK-NEXT: ld 4, .LC0@toc@l(4)
+; CHECK-NEXT: ld 5, .LC1@toc@l(5)
+; CHECK-NEXT: lwz 6, 0(4)
+; CHECK-NEXT: lwz 5, 0(5)
+; CHECK-NEXT: cmpw 6, 5
+; CHECK-NEXT: lwz 5, 0(4)
+; CHECK-NEXT: mr 4, 3
+; CHECK-NEXT: bgt 0, .LBB0_3
+; CHECK-NEXT: # BB#1:
+; CHECK-NEXT: addis 3, 2, .LC0@toc@ha
+; CHECK-NEXT: addis 6, 2, .LC1@toc@ha
+; CHECK-NEXT: ld 3, .LC0@toc@l(3)
+; CHECK-NEXT: ld 6, .LC1@toc@l(6)
+; CHECK-NEXT: .p2align 5
+; CHECK-NEXT: .LBB0_2: # %if.end
+; CHECK-NOT: addis {{[0-9]+}}, 2, .LC0@toc@ha
+; CHECK-NOT: addis {{[0-9]+}}, 2, .LC1@toc@ha
+; CHECK: blr
+entry:
+ %0 = load volatile i32, i32* @ga, align 4
+ %1 = load volatile i32, i32* @gb, align 4
+ %cmp1 = icmp sgt i32 %0, %1
+ %2 = load volatile i32, i32* @ga, align 4
+ br i1 %cmp1, label %if.then, label %if.end
+
+if.then: ; preds = %if.end, %entry
+ %.lcssa = phi i32 [ %2, %entry ], [ %6, %if.end ]
+ %call = tail call signext i32 %FP(i32 signext %.lcssa) #1
+ ret i32 %call
+
+if.end: ; preds = %entry, %if.end
+ %3 = phi i32 [ %6, %if.end ], [ %2, %entry ]
+ %inc = add nsw i32 %3, 1
+ store volatile i32 %inc, i32* @ga, align 4
+ %4 = load volatile i32, i32* @ga, align 4
+ %5 = load volatile i32, i32* @gb, align 4
+ %cmp = icmp sgt i32 %4, %5
+ %6 = load volatile i32, i32* @ga, align 4
+ br i1 %cmp, label %if.then, label %if.end
+}
diff --git a/test/CodeGen/PowerPC/logic-ops-on-compares.ll b/test/CodeGen/PowerPC/logic-ops-on-compares.ll
index 5a507e9ff678..df021c20ea86 100644
--- a/test/CodeGen/PowerPC/logic-ops-on-compares.ll
+++ b/test/CodeGen/PowerPC/logic-ops-on-compares.ll
@@ -40,8 +40,8 @@ return: ; preds = %if.end, %if.then
ret i32 %retval.0
}
-define void @neg_truncate_i32_eq(i32 *%ptr) {
-; CHECK-LABEL: neg_truncate_i32_eq:
+define void @neg_truncate_i32(i32 *%ptr) {
+; CHECK-LABEL: neg_truncate_i32:
; CHECK: # BB#0: # %entry
; CHECK-NEXT: lwz r3, 0(r3)
; CHECK-NEXT: rldicl. r3, r3, 0, 63
@@ -66,8 +66,8 @@ if.end29: ; preds = %if.else
}
; Function Attrs: nounwind
-define i64 @logic_eq_64(i64 %a, i64 %b, i64 %c) {
-; CHECK-LABEL: logic_eq_64:
+define i64 @logic_ne_64(i64 %a, i64 %b, i64 %c) {
+; CHECK-LABEL: logic_ne_64:
; CHECK: xor r7, r3, r4
; CHECK-NEXT: li r6, 55
; CHECK-NEXT: xor r5, r5, r6
@@ -99,8 +99,8 @@ return: ; preds = %if.end, %if.then
ret i64 %retval.0
}
-define void @neg_truncate_i64_eq(i64 *%ptr) {
-; CHECK-LABEL: neg_truncate_i64_eq:
+define void @neg_truncate_i64(i64 *%ptr) {
+; CHECK-LABEL: neg_truncate_i64:
; CHECK: # BB#0: # %entry
; CHECK-NEXT: ld r3, 0(r3)
; CHECK-NEXT: rldicl. r3, r3, 0, 63
@@ -124,67 +124,6 @@ if.end29: ; preds = %if.else
}
-; Function Attrs: nounwind
-define i64 @logic_ne_64(i64 %a, i64 %b, i64 %c) {
-; CHECK-LABEL: logic_ne_64:
-; CHECK: xor r7, r3, r4
-; CHECK-NEXT: li r6, 55
-; CHECK-NEXT: addic r8, r7, -1
-; CHECK-NEXT: xor r5, r5, r6
-; CHECK-NEXT: subfe r7, r8, r7
-; CHECK-NEXT: cntlzd r5, r5
-; CHECK-NEXT: addic r12, r4, -1
-; CHECK-NEXT: rldicl r5, r5, 58, 63
-; CHECK-NEXT: subfe r6, r12, r4
-; CHECK-NEXT: and r6, r7, r6
-; CHECK-NEXT: or. r5, r6, r5
-; CHECK-NEXT: bc 4, 1
-entry:
- %tobool = icmp ne i64 %a, %b
- %tobool1 = icmp ne i64 %b, 0
- %or.cond = and i1 %tobool, %tobool1
- %tobool3 = icmp eq i64 %c, 55
- %or.cond5 = or i1 %or.cond, %tobool3
- br i1 %or.cond5, label %if.end, label %if.then
-
-if.then: ; preds = %entry
- %call = tail call i64 @foo64(i64 %a) #2
- br label %return
-
-if.end: ; preds = %entry
- %call4 = tail call i64 @bar64(i64 %b) #2
- br label %return
-
-return: ; preds = %if.end, %if.then
- %retval.0 = phi i64 [ %call4, %if.end ], [ %call, %if.then ]
- ret i64 %retval.0
-}
-
-define void @neg_truncate_i64_ne(i64 *%ptr) {
-; CHECK-LABEL: neg_truncate_i64_ne:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: ld r3, 0(r3)
-; CHECK-NEXT: andi. r3, r3, 1
-; CHECK-NEXT: bclr 12, 1, 0
-; CHECK-NEXT: # BB#1: # %if.end29.thread136
-; CHECK-NEXT: .LBB5_2: # %if.end29
-entry:
- %0 = load i64, i64* %ptr, align 4
- %rem17127 = and i64 %0, 1
- %cmp18 = icmp ne i64 %rem17127, 0
- br label %if.else
-
-if.else: ; preds = %entry
- br i1 %cmp18, label %if.end29, label %if.end29.thread136
-
-if.end29.thread136: ; preds = %if.else
- unreachable
-
-if.end29: ; preds = %if.else
- ret void
-
-}
-
declare signext i32 @foo(i32 signext)
declare signext i32 @bar(i32 signext)
declare i64 @foo64(i64)
diff --git a/test/CodeGen/PowerPC/ppc64-P9-mod.ll b/test/CodeGen/PowerPC/ppc64-P9-mod.ll
new file mode 100644
index 000000000000..46e347becbb6
--- /dev/null
+++ b/test/CodeGen/PowerPC/ppc64-P9-mod.ll
@@ -0,0 +1,263 @@
+; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr9 -verify-machineinstrs | FileCheck %s
+; RUN: llc < %s -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-PWR8 -implicit-check-not mod[us][wd]
+
+@mod_resultsw = common local_unnamed_addr global i32 0, align 4
+@mod_resultud = common local_unnamed_addr global i64 0, align 8
+@div_resultsw = common local_unnamed_addr global i32 0, align 4
+@mod_resultuw = common local_unnamed_addr global i32 0, align 4
+@div_resultuw = common local_unnamed_addr global i32 0, align 4
+@div_resultsd = common local_unnamed_addr global i64 0, align 8
+@mod_resultsd = common local_unnamed_addr global i64 0, align 8
+@div_resultud = common local_unnamed_addr global i64 0, align 8
+
+; Function Attrs: norecurse nounwind
+define void @modulo_sw(i32 signext %a, i32 signext %b) local_unnamed_addr {
+entry:
+ %rem = srem i32 %a, %b
+ store i32 %rem, i32* @mod_resultsw, align 4
+ ret void
+; CHECK-LABEL: modulo_sw
+; CHECK: modsw {{[0-9]+}}, 3, 4
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_sw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind readnone
+define zeroext i32 @modulo_uw(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr {
+entry:
+ %rem = urem i32 %a, %b
+ ret i32 %rem
+; CHECK-LABEL: modulo_uw
+; CHECK: moduw {{[0-9]+}}, 3, 4
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_uw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind readnone
+define i64 @modulo_sd(i64 %a, i64 %b) local_unnamed_addr {
+entry:
+ %rem = srem i64 %a, %b
+ ret i64 %rem
+; CHECK-LABEL: modulo_sd
+; CHECK: modsd {{[0-9]+}}, 3, 4
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_sd
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+define void @modulo_ud(i64 %a, i64 %b) local_unnamed_addr {
+entry:
+ %rem = urem i64 %a, %b
+ store i64 %rem, i64* @mod_resultud, align 8
+ ret void
+; CHECK-LABEL: modulo_ud
+; CHECK: modud {{[0-9]+}}, 3, 4
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_ud
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+define void @modulo_div_sw(i32 signext %a, i32 signext %b) local_unnamed_addr {
+entry:
+ %rem = srem i32 %a, %b
+ store i32 %rem, i32* @mod_resultsw, align 4
+ %div = sdiv i32 %a, %b
+ store i32 %div, i32* @div_resultsw, align 4
+ ret void
+; CHECK-LABEL: modulo_div_sw
+; CHECK-NOT: modsw
+; CHECK: div
+; CHECK-NOT: modsw
+; CHECK: mull
+; CHECK-NOT: modsw
+; CHECK: sub
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_div_sw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+define void @modulo_div_abc_sw(i32 signext %a, i32 signext %b, i32 signext %c) local_unnamed_addr {
+entry:
+ %rem = srem i32 %a, %c
+ store i32 %rem, i32* @mod_resultsw, align 4
+ %div = sdiv i32 %b, %c
+ store i32 %div, i32* @div_resultsw, align 4
+ ret void
+; CHECK-LABEL: modulo_div_abc_sw
+; CHECK: modsw {{[0-9]+}}, 3, 5
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_div_abc_sw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+define void @modulo_div_uw(i32 zeroext %a, i32 zeroext %b) local_unnamed_addr {
+entry:
+ %rem = urem i32 %a, %b
+ store i32 %rem, i32* @mod_resultuw, align 4
+ %div = udiv i32 %a, %b
+ store i32 %div, i32* @div_resultuw, align 4
+ ret void
+; CHECK-LABEL: modulo_div_uw
+; CHECK-NOT: modsw
+; CHECK: div
+; CHECK-NOT: modsw
+; CHECK: mull
+; CHECK-NOT: modsw
+; CHECK: sub
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_div_uw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+define void @modulo_div_swuw(i32 signext %a, i32 signext %b) local_unnamed_addr {
+entry:
+ %rem = srem i32 %a, %b
+ store i32 %rem, i32* @mod_resultsw, align 4
+ %div = udiv i32 %a, %b
+ store i32 %div, i32* @div_resultsw, align 4
+ ret void
+; CHECK-LABEL: modulo_div_swuw
+; CHECK: modsw {{[0-9]+}}, 3, 4
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_div_swuw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+define void @modulo_div_udsd(i64 %a, i64 %b) local_unnamed_addr {
+entry:
+ %rem = urem i64 %a, %b
+ store i64 %rem, i64* @mod_resultud, align 8
+ %div = sdiv i64 %a, %b
+ store i64 %div, i64* @div_resultsd, align 8
+ ret void
+; CHECK-LABEL: modulo_div_udsd
+; CHECK: modud {{[0-9]+}}, 3, 4
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_div_udsd
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+define void @modulo_const32_sw(i32 signext %a) local_unnamed_addr {
+entry:
+ %rem = srem i32 %a, 32
+ store i32 %rem, i32* @mod_resultsw, align 4
+ ret void
+; CHECK-LABEL: modulo_const32_sw
+; CHECK-NOT: modsw
+; CHECK: srawi
+; CHECK-NOT: modsw
+; CHECK: addze
+; CHECK-NOT: modsw
+; CHECK: slwi
+; CHECK-NOT: modsw
+; CHECK: subf
+; CHECK-NOT: modsw
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_const32_sw
+; CHECK-PWR8: srawi
+; CHECK-PWR8: addze
+; CHECK-PWR8: slwi
+; CHECK-PWR8: subf
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind readnone
+define signext i32 @modulo_const3_sw(i32 signext %a) local_unnamed_addr {
+entry:
+ %rem = srem i32 %a, 3
+ ret i32 %rem
+; CHECK-LABEL: modulo_const3_sw
+; CHECK-NOT: modsw
+; CHECK: mull
+; CHECK-NOT: modsw
+; CHECK: sub
+; CHECK-NOT: modsw
+; CHECK: blr
+; CHECK-PWR8-LABEL: modulo_const3_sw
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind readnone
+define signext i32 @const2_modulo_sw(i32 signext %a) local_unnamed_addr {
+entry:
+ %rem = srem i32 2, %a
+ ret i32 %rem
+; CHECK-LABEL: const2_modulo_sw
+; CHECK: modsw {{[0-9]+}}, {{[0-9]+}}, 3
+; CHECK: blr
+; CHECK-PWR8-LABEL: const2_modulo_sw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+; Function Attrs: norecurse nounwind
+; FIXME On power 9 this test will still produce modsw because the divide is in
+; a different block than the remainder. Due to the nature of the SDAG we cannot
+; see the div in the other block.
+define void @blocks_modulo_div_sw(i32 signext %a, i32 signext %b, i32 signext %c) local_unnamed_addr {
+entry:
+ %div = sdiv i32 %a, %b
+ store i32 %div, i32* @div_resultsw, align 4
+ %cmp = icmp sgt i32 %c, 0
+ br i1 %cmp, label %if.then, label %if.end
+
+if.then: ; preds = %entry
+ %rem = srem i32 %a, %b
+ store i32 %rem, i32* @mod_resultsw, align 4
+ br label %if.end
+
+if.end: ; preds = %if.then, %entry
+ ret void
+; CHECK-LABEL: blocks_modulo_div_sw
+; CHECK: div
+; CHECK: modsw {{[0-9]+}}, 3, 4
+; CHECK: blr
+; CHECK-PWR8-LABEL: blocks_modulo_div_sw
+; CHECK-PWR8: div
+; CHECK-PWR8: mull
+; CHECK-PWR8: sub
+; CHECK-PWR8: blr
+}
+
+
diff --git a/test/CodeGen/PowerPC/testComparesinesll.ll b/test/CodeGen/PowerPC/testComparesinesll.ll
deleted file mode 100644
index 9e9369455857..000000000000
--- a/test/CodeGen/PowerPC/testComparesinesll.ll
+++ /dev/null
@@ -1,125 +0,0 @@
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-
-@glob = common local_unnamed_addr global i64 0, align 8
-
-define signext i32 @test_inesll(i64 %a, i64 %b) {
-; CHECK-LABEL: test_inesll:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv = zext i1 %cmp to i32
- ret i32 %conv
-}
-
-define signext i32 @test_inesll_sext(i64 %a, i64 %b) {
-; CHECK-LABEL: test_inesll_sext:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %sub = sext i1 %cmp to i32
- ret i32 %sub
-}
-
-define signext i32 @test_inesll_z(i64 %a) {
-; CHECK-LABEL: test_inesll_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv = zext i1 %cmp to i32
- ret i32 %conv
-}
-
-define signext i32 @test_inesll_sext_z(i64 %a) {
-; CHECK-LABEL: test_inesll_sext_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %sub = sext i1 %cmp to i32
- ret i32 %sub
-}
-
-define void @test_inesll_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_inesll_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_inesll_sext_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_inesll_sext_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_inesll_z_store(i64 %a) {
-; CHECK-LABEL: test_inesll_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_inesll_sext_z_store(i64 %a) {
-; CHECK-LABEL: test_inesll_sext_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
diff --git a/test/CodeGen/PowerPC/testComparesineull.ll b/test/CodeGen/PowerPC/testComparesineull.ll
deleted file mode 100644
index 7f0fed15157c..000000000000
--- a/test/CodeGen/PowerPC/testComparesineull.ll
+++ /dev/null
@@ -1,125 +0,0 @@
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-
-@glob = common local_unnamed_addr global i64 0, align 8
-
-define signext i32 @test_ineull(i64 %a, i64 %b) {
-; CHECK-LABEL: test_ineull:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv = zext i1 %cmp to i32
- ret i32 %conv
-}
-
-define signext i32 @test_ineull_sext(i64 %a, i64 %b) {
-; CHECK-LABEL: test_ineull_sext:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %sub = sext i1 %cmp to i32
- ret i32 %sub
-}
-
-define signext i32 @test_ineull_z(i64 %a) {
-; CHECK-LABEL: test_ineull_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv = zext i1 %cmp to i32
- ret i32 %conv
-}
-
-define signext i32 @test_ineull_sext_z(i64 %a) {
-; CHECK-LABEL: test_ineull_sext_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %sub = sext i1 %cmp to i32
- ret i32 %sub
-}
-
-define void @test_ineull_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_ineull_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_ineull_sext_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_ineull_sext_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_ineull_z_store(i64 %a) {
-; CHECK-LABEL: test_ineull_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_ineull_sext_z_store(i64 %a) {
-; CHECK-LABEL: test_ineull_sext_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
diff --git a/test/CodeGen/PowerPC/testComparesllnesll.ll b/test/CodeGen/PowerPC/testComparesllnesll.ll
deleted file mode 100644
index d87ff55739fc..000000000000
--- a/test/CodeGen/PowerPC/testComparesllnesll.ll
+++ /dev/null
@@ -1,125 +0,0 @@
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-
-@glob = common local_unnamed_addr global i64 0, align 8
-
-define i64 @test_llnesll(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llnesll:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = zext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define i64 @test_llnesll_sext(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llnesll_sext:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = sext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define i64 @test_llnesll_z(i64 %a) {
-; CHECK-LABEL: test_llnesll_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = zext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define i64 @test_llnesll_sext_z(i64 %a) {
-; CHECK-LABEL: test_llnesll_sext_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = sext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define void @test_llnesll_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llnesll_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_llnesll_sext_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llnesll_sext_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_llnesll_z_store(i64 %a) {
-; CHECK-LABEL: test_llnesll_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_llnesll_sext_z_store(i64 %a) {
-; CHECK-LABEL: test_llnesll_sext_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
diff --git a/test/CodeGen/PowerPC/testComparesllneull.ll b/test/CodeGen/PowerPC/testComparesllneull.ll
deleted file mode 100644
index 7309d5899068..000000000000
--- a/test/CodeGen/PowerPC/testComparesllneull.ll
+++ /dev/null
@@ -1,125 +0,0 @@
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -O2 \
-; RUN: -ppc-asm-full-reg-names -mcpu=pwr8 < %s | FileCheck %s \
-; RUN: --implicit-check-not cmpw --implicit-check-not cmpd --implicit-check-not cmpl
-; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-
-@glob = common local_unnamed_addr global i64 0, align 8
-
-define i64 @test_llneull(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llneull:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = zext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define i64 @test_llneull_sext(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llneull_sext:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = sext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define i64 @test_llneull_z(i64 %a) {
-; CHECK-LABEL: test_llneull_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addic r4, r3, -1
-; CHECK-NEXT: subfe r3, r4, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = zext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define i64 @test_llneull_sext_z(i64 %a) {
-; CHECK-LABEL: test_llneull_sext_z:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = sext i1 %cmp to i64
- ret i64 %conv1
-}
-
-define void @test_llneull_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llneull_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_llneull_sext_store(i64 %a, i64 %b) {
-; CHECK-LABEL: test_llneull_sext_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r5, r2, .LC0@toc@ha
-; CHECK-NEXT: xor r3, r3, r4
-; CHECK-NEXT: ld r12, .LC0@toc@l(r5)
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r12)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, %b
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_llneull_z_store(i64 %a) {
-; CHECK-LABEL: test_llneull_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: addic r5, r3, -1
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r5, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = zext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
-
-define void @test_llneull_sext_z_store(i64 %a) {
-; CHECK-LABEL: test_llneull_sext_z_store:
-; CHECK: # BB#0: # %entry
-; CHECK-NEXT: addis r4, r2, .LC0@toc@ha
-; CHECK-NEXT: subfic r3, r3, 0
-; CHECK-NEXT: ld r4, .LC0@toc@l(r4)
-; CHECK-NEXT: subfe r3, r3, r3
-; CHECK-NEXT: std r3, 0(r4)
-; CHECK-NEXT: blr
-entry:
- %cmp = icmp ne i64 %a, 0
- %conv1 = sext i1 %cmp to i64
- store i64 %conv1, i64* @glob, align 8
- ret void
-}
diff --git a/test/CodeGen/PowerPC/vec_revb.ll b/test/CodeGen/PowerPC/vec_revb.ll
new file mode 100644
index 000000000000..c09164bae13e
--- /dev/null
+++ b/test/CodeGen/PowerPC/vec_revb.ll
@@ -0,0 +1,54 @@
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr9 < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu -mcpu=pwr9 < %s | FileCheck %s
+
+define <8 x i16> @testXXBRH(<8 x i16> %a) {
+; CHECK-LABEL: testXXBRH:
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: xxbrh 34, 34
+; CHECK-NEXT: blr
+
+entry:
+ %0 = bitcast <8 x i16> %a to <16 x i8>
+ %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6, i32 9, i32 8, i32 11, i32 10, i32 13, i32 12, i32 15, i32 14>
+ %2 = bitcast <16 x i8> %1 to <8 x i16>
+ ret <8 x i16> %2
+}
+
+define <4 x i32> @testXXBRW(<4 x i32> %a) {
+; CHECK-LABEL: testXXBRW:
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: xxbrw 34, 34
+; CHECK-NEXT: blr
+
+entry:
+ %0 = bitcast <4 x i32> %a to <16 x i8>
+ %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
+ %2 = bitcast <16 x i8> %1 to <4 x i32>
+ ret <4 x i32> %2
+}
+
+define <2 x double> @testXXBRD(<2 x double> %a) {
+; CHECK-LABEL: testXXBRD:
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: xxbrd 34, 34
+; CHECK-NEXT: blr
+
+entry:
+ %0 = bitcast <2 x double> %a to <16 x i8>
+ %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
+ %2 = bitcast <16 x i8> %1 to <2 x double>
+ ret <2 x double> %2
+}
+
+define <1 x i128> @testXXBRQ(<1 x i128> %a) {
+; CHECK-LABEL: testXXBRQ:
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: xxbrq 34, 34
+; CHECK-NEXT: blr
+
+entry:
+ %0 = bitcast <1 x i128> %a to <16 x i8>
+ %1 = shufflevector <16 x i8> %0, <16 x i8> undef, <16 x i32> <i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %2 = bitcast <16 x i8> %1 to <1 x i128>
+ ret <1 x i128> %2
+}
diff --git a/test/CodeGen/SystemZ/fp-sincos-01.ll b/test/CodeGen/SystemZ/fp-sincos-01.ll
index cd182a590eee..4a38d7afba2c 100644
--- a/test/CodeGen/SystemZ/fp-sincos-01.ll
+++ b/test/CodeGen/SystemZ/fp-sincos-01.ll
@@ -1,6 +1,6 @@
; Test that combined sin/cos library call is emitted when appropriate
-; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=CHECK-NOOPT
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=CHECK-OPT
; RUN: llc < %s -mtriple=s390x-linux-gnu -enable-unsafe-fp-math | FileCheck %s --check-prefix=CHECK-OPT
define float @f1(float %x) {
@@ -8,10 +8,18 @@ define float @f1(float %x) {
; CHECK-OPT: brasl %r14, sincosf@PLT
; CHECK-OPT: le %f0, 164(%r15)
; CHECK-OPT: aeb %f0, 160(%r15)
+ %tmp1 = call float @sinf(float %x) readnone
+ %tmp2 = call float @cosf(float %x) readnone
+ %add = fadd float %tmp1, %tmp2
+ ret float %add
+}
-; CHECK-NOOPT-LABEL: f1:
-; CHECK-NOOPT: brasl %r14, sinf@PLT
-; CHECK-NOOPT: brasl %r14, cosf@PLT
+define float @f1_errno(float %x) {
+; CHECK-OPT-LABEL: f1_errno:
+; CHECK-OPT: brasl %r14, sinf@PLT
+; CHECK-OPT: ler %f9, %f0
+; CHECK-OPT: brasl %r14, cosf@PLT
+; CHECK-OPT: aebr %f0, %f9
%tmp1 = call float @sinf(float %x)
%tmp2 = call float @cosf(float %x)
%add = fadd float %tmp1, %tmp2
@@ -23,10 +31,18 @@ define double @f2(double %x) {
; CHECK-OPT: brasl %r14, sincos@PLT
; CHECK-OPT: ld %f0, 168(%r15)
; CHECK-OPT: adb %f0, 160(%r15)
+ %tmp1 = call double @sin(double %x) readnone
+ %tmp2 = call double @cos(double %x) readnone
+ %add = fadd double %tmp1, %tmp2
+ ret double %add
+}
-; CHECK-NOOPT-LABEL: f2:
-; CHECK-NOOPT: brasl %r14, sin@PLT
-; CHECK-NOOPT: brasl %r14, cos@PLT
+define double @f2_errno(double %x) {
+; CHECK-OPT-LABEL: f2_errno:
+; CHECK-OPT: brasl %r14, sin@PLT
+; CHECK-OPT: ldr %f9, %f0
+; CHECK-OPT: brasl %r14, cos@PLT
+; CHECK-OPT: adbr %f0, %f9
%tmp1 = call double @sin(double %x)
%tmp2 = call double @cos(double %x)
%add = fadd double %tmp1, %tmp2
@@ -37,20 +53,27 @@ define fp128 @f3(fp128 %x) {
; CHECK-OPT-LABEL: f3:
; CHECK-OPT: brasl %r14, sincosl@PLT
; CHECK-OPT: axbr
+ %tmp1 = call fp128 @sinl(fp128 %x) readnone
+ %tmp2 = call fp128 @cosl(fp128 %x) readnone
+ %add = fadd fp128 %tmp1, %tmp2
+ ret fp128 %add
+}
-; CHECK-NOOPT-LABEL: f3:
-; CHECK-NOOPT: brasl %r14, sinl@PLT
-; CHECK-NOOPT: brasl %r14, cosl@PLT
+define fp128 @f3_errno(fp128 %x) {
+; CHECK-OPT-LABEL: f3_errno:
+; CHECK-OPT: brasl %r14, sinl@PLT
+; CHECK-OPT: brasl %r14, cosl@PLT
+; CHECK-OPT: axbr
%tmp1 = call fp128 @sinl(fp128 %x)
%tmp2 = call fp128 @cosl(fp128 %x)
%add = fadd fp128 %tmp1, %tmp2
ret fp128 %add
}
-declare float @sinf(float) readonly
-declare double @sin(double) readonly
-declare fp128 @sinl(fp128) readonly
-declare float @cosf(float) readonly
-declare double @cos(double) readonly
-declare fp128 @cosl(fp128) readonly
+declare float @sinf(float)
+declare double @sin(double)
+declare fp128 @sinl(fp128)
+declare float @cosf(float)
+declare double @cos(double)
+declare fp128 @cosl(fp128)
diff --git a/test/CodeGen/X86/2012-01-11-split-cv.ll b/test/CodeGen/X86/2012-01-11-split-cv.ll
index 212acedafb94..34ec48a02517 100644
--- a/test/CodeGen/X86/2012-01-11-split-cv.ll
+++ b/test/CodeGen/X86/2012-01-11-split-cv.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mattr=+avx -mtriple=i686-unknown-unknown | FileCheck %s
define void @add18i16(<18 x i16>* nocapture sret %ret, <18 x i16>* %bp) nounwind {
@@ -12,7 +12,6 @@ define void @add18i16(<18 x i16>* nocapture sret %ret, <18 x i16>* %bp) nounwind
; CHECK-NEXT: vmovups %ymm0, (%eax)
; CHECK-NEXT: vzeroupper
; CHECK-NEXT: retl $4
-;
%b = load <18 x i16>, <18 x i16>* %bp, align 16
%x = add <18 x i16> zeroinitializer, %b
store <18 x i16> %x, <18 x i16>* %ret, align 16
diff --git a/test/CodeGen/X86/StackColoring.ll b/test/CodeGen/X86/StackColoring.ll
index 93888c470e2d..47c74175f949 100644
--- a/test/CodeGen/X86/StackColoring.ll
+++ b/test/CodeGen/X86/StackColoring.ll
@@ -582,12 +582,76 @@ if.end: ; preds = %if.then, %entry
ret i32 %x.addr.0
}
+;CHECK-LABEL: multi_segment:
+;YESCOLOR: subq $256, %rsp
+;NOFIRSTUSE: subq $256, %rsp
+;NOCOLOR: subq $512, %rsp
+define i1 @multi_segment(i1, i1)
+{
+entry-block:
+ %foo = alloca [32 x i64]
+ %bar = alloca [32 x i64]
+ %foo_i8 = bitcast [32 x i64]* %foo to i8*
+ %bar_i8 = bitcast [32 x i64]* %bar to i8*
+ call void @llvm.lifetime.start.p0i8(i64 256, i8* %bar_i8)
+ call void @baz([32 x i64]* %bar, i32 1)
+ call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8)
+ call void @llvm.lifetime.start.p0i8(i64 256, i8* %foo_i8)
+ call void @baz([32 x i64]* %foo, i32 1)
+ call void @llvm.lifetime.end.p0i8(i64 256, i8* %foo_i8)
+ call void @llvm.lifetime.start.p0i8(i64 256, i8* %bar_i8)
+ call void @baz([32 x i64]* %bar, i32 1)
+ call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8)
+ ret i1 true
+}
+
+;CHECK-LABEL: pr32488:
+;YESCOLOR: subq $256, %rsp
+;NOFIRSTUSE: subq $256, %rsp
+;NOCOLOR: subq $512, %rsp
+define i1 @pr32488(i1, i1)
+{
+entry-block:
+ %foo = alloca [32 x i64]
+ %bar = alloca [32 x i64]
+ %foo_i8 = bitcast [32 x i64]* %foo to i8*
+ %bar_i8 = bitcast [32 x i64]* %bar to i8*
+ br i1 %0, label %if_false, label %if_true
+if_false:
+ call void @llvm.lifetime.start.p0i8(i64 256, i8* %bar_i8)
+ call void @baz([32 x i64]* %bar, i32 0)
+ br i1 %1, label %if_false.1, label %onerr
+if_false.1:
+ call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8)
+ br label %merge
+if_true:
+ call void @llvm.lifetime.start.p0i8(i64 256, i8* %foo_i8)
+ call void @baz([32 x i64]* %foo, i32 1)
+ br i1 %1, label %if_true.1, label %onerr
+if_true.1:
+ call void @llvm.lifetime.end.p0i8(i64 256, i8* %foo_i8)
+ br label %merge
+merge:
+ ret i1 false
+onerr:
+ call void @llvm.lifetime.end.p0i8(i64 256, i8* %foo_i8)
+ call void @llvm.lifetime.end.p0i8(i64 256, i8* %bar_i8)
+ call void @destructor()
+ ret i1 true
+}
+
+%Data = type { [32 x i64] }
+
+declare void @destructor()
+
declare void @inita(i32*)
declare void @initb(i32*,i32*,i32*)
declare void @bar([100 x i32]* , [100 x i32]*) nounwind
+declare void @baz([32 x i64]*, i32)
+
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind
diff --git a/test/CodeGen/X86/add-sub-nsw-nuw.ll b/test/CodeGen/X86/add-sub-nsw-nuw.ll
index f5bffb2386bd..d02736de55d3 100644
--- a/test/CodeGen/X86/add-sub-nsw-nuw.ll
+++ b/test/CodeGen/X86/add-sub-nsw-nuw.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=i386-apple-darwin < %s | FileCheck %s
; PR30841: https://llvm.org/bugs/show_bug.cgi?id=30841
@@ -12,7 +12,6 @@ define i8 @PR30841(i64 %argc) {
; CHECK-NEXT: negl %eax
; CHECK-NEXT: ## kill: %AL<def> %AL<kill> %EAX<kill>
; CHECK-NEXT: retl
-;
entry:
%or = or i64 %argc, -4294967296
br label %end
diff --git a/test/CodeGen/X86/addcarry.ll b/test/CodeGen/X86/addcarry.ll
index 3c84af4aa9ec..cffcfd8e8a42 100644
--- a/test/CodeGen/X86/addcarry.ll
+++ b/test/CodeGen/X86/addcarry.ll
@@ -81,6 +81,30 @@ entry:
ret void
}
+define i8 @e(i32* nocapture %a, i32 %b) nounwind {
+; CHECK-LABEL: e:
+; CHECK: # BB#0:
+; CHECK-NEXT: # kill: %ESI<def> %ESI<kill> %RSI<def>
+; CHECK-NEXT: movl (%rdi), %ecx
+; CHECK-NEXT: leal (%rsi,%rcx), %edx
+; CHECK-NEXT: addl %esi, %edx
+; CHECK-NEXT: setb %al
+; CHECK-NEXT: addl %esi, %ecx
+; CHECK-NEXT: movl %edx, (%rdi)
+; CHECK-NEXT: adcb $0, %al
+; CHECK-NEXT: retq
+ %1 = load i32, i32* %a, align 4
+ %2 = add i32 %1, %b
+ %3 = icmp ult i32 %2, %b
+ %4 = zext i1 %3 to i8
+ %5 = add i32 %2, %b
+ store i32 %5, i32* %a, align 4
+ %6 = icmp ult i32 %5, %b
+ %7 = zext i1 %6 to i8
+ %8 = add nuw nsw i8 %7, %4
+ ret i8 %8
+}
+
%scalar = type { [4 x i64] }
define %scalar @pr31719(%scalar* nocapture readonly %this, %scalar %arg.b) {
diff --git a/test/CodeGen/X86/avx-vperm2x128.ll b/test/CodeGen/X86/avx-vperm2x128.ll
index f4a77c370db5..9a21f4b5caba 100644
--- a/test/CodeGen/X86/avx-vperm2x128.ll
+++ b/test/CodeGen/X86/avx-vperm2x128.ll
@@ -50,16 +50,10 @@ entry:
}
define <8 x float> @shuffle_v8f32_01230123_mem(<8 x float>* %pa, <8 x float>* %pb) nounwind uwtable readnone ssp {
-; AVX1-LABEL: shuffle_v8f32_01230123_mem:
-; AVX1: ## BB#0: ## %entry
-; AVX1-NEXT: vmovaps (%rdi), %ymm0
-; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0
-; AVX1-NEXT: retq
-;
-; AVX2-LABEL: shuffle_v8f32_01230123_mem:
-; AVX2: ## BB#0: ## %entry
-; AVX2-NEXT: vperm2f128 {{.*#+}} ymm0 = mem[0,1,0,1]
-; AVX2-NEXT: retq
+; ALL-LABEL: shuffle_v8f32_01230123_mem:
+; ALL: ## BB#0: ## %entry
+; ALL-NEXT: vperm2f128 {{.*#+}} ymm0 = mem[0,1,0,1]
+; ALL-NEXT: retq
entry:
%a = load <8 x float>, <8 x float>* %pa
%b = load <8 x float>, <8 x float>* %pb
@@ -195,17 +189,15 @@ define <16 x i16> @shuffle_v16i16_4501_mem(<16 x i16>* %a, <16 x i16>* %b) nounw
; AVX1-LABEL: shuffle_v16i16_4501_mem:
; AVX1: ## BB#0: ## %entry
; AVX1-NEXT: vmovdqa (%rdi), %ymm0
-; AVX1-NEXT: vmovaps (%rsi), %ymm1
; AVX1-NEXT: vpaddw {{.*}}(%rip), %xmm0, %xmm0
-; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm1, %ymm0
+; AVX1-NEXT: vperm2f128 {{.*#+}} ymm0 = mem[0,1],ymm0[0,1]
; AVX1-NEXT: retq
;
; AVX2-LABEL: shuffle_v16i16_4501_mem:
; AVX2: ## BB#0: ## %entry
; AVX2-NEXT: vmovdqa (%rdi), %ymm0
-; AVX2-NEXT: vmovdqa (%rsi), %ymm1
; AVX2-NEXT: vpaddw {{.*}}(%rip), %ymm0, %ymm0
-; AVX2-NEXT: vinserti128 $1, %xmm0, %ymm1, %ymm0
+; AVX2-NEXT: vperm2i128 {{.*#+}} ymm0 = mem[0,1],ymm0[0,1]
; AVX2-NEXT: retq
entry:
%c = load <16 x i16>, <16 x i16>* %a
diff --git a/test/CodeGen/X86/bt.ll b/test/CodeGen/X86/bt.ll
index cebcba38bd4f..064058115684 100644
--- a/test/CodeGen/X86/bt.ll
+++ b/test/CodeGen/X86/bt.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s
; PR3253
@@ -24,7 +24,12 @@ define void @test2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB0_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB0_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -44,7 +49,13 @@ define void @test2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB1_1
-;
+; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
+; CHECK-NEXT: .LBB1_1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -64,7 +75,12 @@ define void @atest2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB2_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB2_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -84,7 +100,13 @@ define void @atest2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB3_1
-;
+; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
+; CHECK-NEXT: .LBB3_1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -104,7 +126,13 @@ define void @test3(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB4_1
-;
+; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
+; CHECK-NEXT: .LBB4_1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %tmp29, %x
@@ -124,7 +152,13 @@ define void @test3b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB5_1
-;
+; CHECK-NEXT: # BB#2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
+; CHECK-NEXT: .LBB5_1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %x, %tmp29
@@ -144,7 +178,12 @@ define void @testne2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB6_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB6_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -164,7 +203,12 @@ define void @testne2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB7_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB7_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -184,7 +228,12 @@ define void @atestne2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB8_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB8_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -204,7 +253,12 @@ define void @atestne2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB9_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB9_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -224,7 +278,12 @@ define void @testne3(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB10_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB10_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %tmp29, %x
@@ -244,7 +303,12 @@ define void @testne3b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB11_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB11_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %x, %tmp29
@@ -264,7 +328,12 @@ define void @query2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB12_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB12_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -284,7 +353,12 @@ define void @query2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB13_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB13_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -304,7 +378,12 @@ define void @aquery2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB14_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB14_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -324,7 +403,12 @@ define void @aquery2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB15_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB15_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -344,7 +428,12 @@ define void @query3(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB16_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB16_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %tmp29, %x
@@ -364,7 +453,12 @@ define void @query3b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB17_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB17_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %x, %tmp29
@@ -384,7 +478,12 @@ define void @query3x(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB18_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB18_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %tmp29, %x
@@ -404,7 +503,12 @@ define void @query3bx(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jae .LBB19_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB19_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %x, %tmp29
@@ -424,7 +528,12 @@ define void @queryne2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB20_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB20_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -444,7 +553,12 @@ define void @queryne2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB21_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB21_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = lshr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -464,7 +578,12 @@ define void @aqueryne2(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB22_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB22_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 %tmp29, 1
@@ -484,7 +603,12 @@ define void @aqueryne2b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB23_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB23_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = ashr i32 %x, %n
%tmp3 = and i32 1, %tmp29
@@ -504,7 +628,12 @@ define void @queryne3(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB24_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB24_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %tmp29, %x
@@ -524,7 +653,12 @@ define void @queryne3b(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB25_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB25_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %x, %tmp29
@@ -544,7 +678,12 @@ define void @queryne3x(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB26_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB26_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %tmp29, %x
@@ -564,7 +703,12 @@ define void @queryne3bx(i32 %x, i32 %n) nounwind {
; CHECK: # BB#0: # %entry
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: jb .LBB27_2
-;
+; CHECK-NEXT: # BB#1: # %bb
+; CHECK-NEXT: pushq %rax
+; CHECK-NEXT: callq foo
+; CHECK-NEXT: popq %rax
+; CHECK-NEXT: .LBB27_2: # %UnifiedReturnBlock
+; CHECK-NEXT: retq
entry:
%tmp29 = shl i32 1, %n
%tmp3 = and i32 %x, %tmp29
@@ -588,7 +732,6 @@ define zeroext i1 @invert(i32 %flags, i32 %flag) nounwind {
; CHECK-NEXT: btl %esi, %edi
; CHECK-NEXT: setb %al
; CHECK-NEXT: retq
-;
%neg = xor i32 %flags, -1
%shl = shl i32 1, %flag
%and = and i32 %shl, %neg
@@ -598,8 +741,10 @@ define zeroext i1 @invert(i32 %flags, i32 %flag) nounwind {
define zeroext i1 @extend(i32 %bit, i64 %bits) {
; CHECK-LABEL: extend:
-; CHECK: # BB#0:
-; CHECK-NEXT: btl %edi, %esi
+; CHECK: # BB#0: # %entry
+; CHECK-NEXT: btl %edi, %esi
+; CHECK-NEXT: setb %al
+; CHECK-NEXT: retq
entry:
%and = and i32 %bit, 31
%sh_prom = zext i32 %and to i64
diff --git a/test/CodeGen/X86/cmov-into-branch.ll b/test/CodeGen/X86/cmov-into-branch.ll
index 6e4762b2e793..e38039501646 100644
--- a/test/CodeGen/X86/cmov-into-branch.ll
+++ b/test/CodeGen/X86/cmov-into-branch.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
; cmp with single-use load, should not form branch.
@@ -9,7 +9,6 @@ define i32 @test1(double %a, double* nocapture %b, i32 %x, i32 %y) {
; CHECK-NEXT: cmovbel %edx, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: retq
-;
%load = load double, double* %b, align 8
%cmp = fcmp olt double %load, %a
%cond = select i1 %cmp, i32 %x, i32 %y
@@ -24,7 +23,6 @@ define i32 @test2(double %a, double %b, i32 %x, i32 %y) {
; CHECK-NEXT: cmovbel %esi, %edi
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-;
%cmp = fcmp ogt double %a, %b
%cond = select i1 %cmp, i32 %x, i32 %y
ret i32 %cond
@@ -39,7 +37,6 @@ define i32 @test4(i32 %a, i32* nocapture %b, i32 %x, i32 %y) {
; CHECK-NEXT: cmovael %ecx, %edx
; CHECK-NEXT: addl %edx, %eax
; CHECK-NEXT: retq
-;
%load = load i32, i32* %b, align 4
%cmp = icmp ult i32 %load, %a
%cond = select i1 %cmp, i32 %x, i32 %y
@@ -56,7 +53,6 @@ define i32 @test5(i32 %a, i32* nocapture %b, i32 %x, i32 %y) {
; CHECK-NEXT: cmovael %edx, %ecx
; CHECK-NEXT: movl %ecx, %eax
; CHECK-NEXT: retq
-;
%load = load i32, i32* %b, align 4
%cmp = icmp ult i32 %load, %a
%cmp1 = icmp ugt i32 %load, %a
@@ -73,7 +69,6 @@ define i32 @weighted_select1(i32 %a, i32 %b) {
; CHECK-NEXT: cmovnel %edi, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: retq
-;
%cmp = icmp ne i32 %a, 0
%sel = select i1 %cmp, i32 %a, i32 %b, !prof !0
ret i32 %sel
@@ -84,12 +79,12 @@ define i32 @weighted_select2(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select2:
; CHECK: # BB#0:
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: jne [[LABEL_BB5:.*]]
-; CHECK: movl %esi, %edi
-; CHECK-NEXT: [[LABEL_BB5]]
+; CHECK-NEXT: jne .LBB5_2
+; CHECK-NEXT: # BB#1: # %select.false
+; CHECK-NEXT: movl %esi, %edi
+; CHECK-NEXT: .LBB5_2: # %select.end
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-;
%cmp = icmp ne i32 %a, 0
%sel = select i1 %cmp, i32 %a, i32 %b, !prof !1
ret i32 %sel
@@ -103,14 +98,14 @@ define i32 @weighted_select3(i32 %a, i32 %b) {
; CHECK-LABEL: weighted_select3:
; CHECK: # BB#0:
; CHECK-NEXT: testl %edi, %edi
-; CHECK-NEXT: je [[LABEL_BB6:.*]]
-; CHECK: movl %edi, %eax
+; CHECK-NEXT: je .LBB6_1
+; CHECK-NEXT: # BB#2: # %select.end
+; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-; CHECK: [[LABEL_BB6]]
+; CHECK-NEXT: .LBB6_1: # %select.false
; CHECK-NEXT: movl %esi, %edi
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-;
%cmp = icmp ne i32 %a, 0
%sel = select i1 %cmp, i32 %a, i32 %b, !prof !2
ret i32 %sel
@@ -124,7 +119,6 @@ define i32 @unweighted_select(i32 %a, i32 %b) {
; CHECK-NEXT: cmovnel %edi, %esi
; CHECK-NEXT: movl %esi, %eax
; CHECK-NEXT: retq
-;
%cmp = icmp ne i32 %a, 0
%sel = select i1 %cmp, i32 %a, i32 %b, !prof !3
ret i32 %sel
diff --git a/test/CodeGen/X86/combine-64bit-vec-binop.ll b/test/CodeGen/X86/combine-64bit-vec-binop.ll
index 2842cb1d9b6e..2935a2095bbf 100644
--- a/test/CodeGen/X86/combine-64bit-vec-binop.ll
+++ b/test/CodeGen/X86/combine-64bit-vec-binop.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s --check-prefix=SSE41
define double @test1_add(double %A, double %B) {
@@ -6,7 +6,6 @@ define double @test1_add(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: paddd %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x i32>
%2 = bitcast double %B to <2 x i32>
%add = add <2 x i32> %1, %2
@@ -19,7 +18,6 @@ define double @test2_add(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: paddw %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <4 x i16>
%2 = bitcast double %B to <4 x i16>
%add = add <4 x i16> %1, %2
@@ -32,7 +30,6 @@ define double @test3_add(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: paddb %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <8 x i8>
%2 = bitcast double %B to <8 x i8>
%add = add <8 x i8> %1, %2
@@ -45,7 +42,6 @@ define double @test1_sub(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: psubd %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x i32>
%2 = bitcast double %B to <2 x i32>
%sub = sub <2 x i32> %1, %2
@@ -58,7 +54,6 @@ define double @test2_sub(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: psubw %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <4 x i16>
%2 = bitcast double %B to <4 x i16>
%sub = sub <4 x i16> %1, %2
@@ -71,7 +66,6 @@ define double @test3_sub(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: psubb %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <8 x i8>
%2 = bitcast double %B to <8 x i8>
%sub = sub <8 x i8> %1, %2
@@ -84,7 +78,6 @@ define double @test1_mul(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: pmulld %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x i32>
%2 = bitcast double %B to <2 x i32>
%mul = mul <2 x i32> %1, %2
@@ -97,7 +90,6 @@ define double @test2_mul(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: pmullw %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <4 x i16>
%2 = bitcast double %B to <4 x i16>
%mul = mul <4 x i16> %1, %2
@@ -114,7 +106,6 @@ define double @test3_mul(double %A, double %B) {
; SSE41-NEXT: pmullw %xmm2, %xmm0
; SSE41-NEXT: pshufb {{.*#+}} xmm0 = xmm0[0,2,4,6,8,10,12,14,u,u,u,u,u,u,u,u]
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <8 x i8>
%2 = bitcast double %B to <8 x i8>
%mul = mul <8 x i8> %1, %2
@@ -127,7 +118,6 @@ define double @test1_and(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: andps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x i32>
%2 = bitcast double %B to <2 x i32>
%and = and <2 x i32> %1, %2
@@ -140,7 +130,6 @@ define double @test2_and(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: andps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <4 x i16>
%2 = bitcast double %B to <4 x i16>
%and = and <4 x i16> %1, %2
@@ -153,7 +142,6 @@ define double @test3_and(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: andps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <8 x i8>
%2 = bitcast double %B to <8 x i8>
%and = and <8 x i8> %1, %2
@@ -166,7 +154,6 @@ define double @test1_or(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: orps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x i32>
%2 = bitcast double %B to <2 x i32>
%or = or <2 x i32> %1, %2
@@ -179,7 +166,6 @@ define double @test2_or(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: orps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <4 x i16>
%2 = bitcast double %B to <4 x i16>
%or = or <4 x i16> %1, %2
@@ -192,7 +178,6 @@ define double @test3_or(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: orps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <8 x i8>
%2 = bitcast double %B to <8 x i8>
%or = or <8 x i8> %1, %2
@@ -205,7 +190,6 @@ define double @test1_xor(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: xorps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x i32>
%2 = bitcast double %B to <2 x i32>
%xor = xor <2 x i32> %1, %2
@@ -218,7 +202,6 @@ define double @test2_xor(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: xorps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <4 x i16>
%2 = bitcast double %B to <4 x i16>
%xor = xor <4 x i16> %1, %2
@@ -231,7 +214,6 @@ define double @test3_xor(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: xorps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <8 x i8>
%2 = bitcast double %B to <8 x i8>
%xor = xor <8 x i8> %1, %2
@@ -244,7 +226,6 @@ define double @test_fadd(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: addps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x float>
%2 = bitcast double %B to <2 x float>
%add = fadd <2 x float> %1, %2
@@ -257,7 +238,6 @@ define double @test_fsub(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: subps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x float>
%2 = bitcast double %B to <2 x float>
%sub = fsub <2 x float> %1, %2
@@ -270,7 +250,6 @@ define double @test_fmul(double %A, double %B) {
; SSE41: # BB#0:
; SSE41-NEXT: mulps %xmm1, %xmm0
; SSE41-NEXT: retq
-;
%1 = bitcast double %A to <2 x float>
%2 = bitcast double %B to <2 x float>
%mul = fmul <2 x float> %1, %2
diff --git a/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll b/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll
index 4dc5b1ba0339..9dd184c8ab31 100644
--- a/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll
+++ b/test/CodeGen/X86/element-wise-atomic-memory-intrinsics.ll
@@ -2,47 +2,47 @@
define i8* @test_memcpy1(i8* %P, i8* %Q) {
; CHECK: test_memcpy
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %P, i8* align 4 %Q, i64 1, i32 1)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 1, i32 1)
ret i8* %P
+ ; 3rd arg (%edx) -- length
; CHECK-DAG: movl $1, %edx
- ; CHECK-DAG: movl $1, %ecx
- ; CHECK: __llvm_memcpy_element_atomic_1
+ ; CHECK: __llvm_memcpy_element_unordered_atomic_1
}
define i8* @test_memcpy2(i8* %P, i8* %Q) {
; CHECK: test_memcpy2
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %P, i8* align 4 %Q, i64 2, i32 2)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 2, i32 2)
ret i8* %P
+ ; 3rd arg (%edx) -- length
; CHECK-DAG: movl $2, %edx
- ; CHECK-DAG: movl $2, %ecx
- ; CHECK: __llvm_memcpy_element_atomic_2
+ ; CHECK: __llvm_memcpy_element_unordered_atomic_2
}
define i8* @test_memcpy4(i8* %P, i8* %Q) {
; CHECK: test_memcpy4
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %P, i8* align 4 %Q, i64 4, i32 4)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 4, i32 4)
ret i8* %P
+ ; 3rd arg (%edx) -- length
; CHECK-DAG: movl $4, %edx
- ; CHECK-DAG: movl $4, %ecx
- ; CHECK: __llvm_memcpy_element_atomic_4
+ ; CHECK: __llvm_memcpy_element_unordered_atomic_4
}
define i8* @test_memcpy8(i8* %P, i8* %Q) {
; CHECK: test_memcpy8
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 8 %P, i8* align 8 %Q, i64 8, i32 8)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 8 %P, i8* align 8 %Q, i32 8, i32 8)
ret i8* %P
+ ; 3rd arg (%edx) -- length
; CHECK-DAG: movl $8, %edx
- ; CHECK-DAG: movl $8, %ecx
- ; CHECK: __llvm_memcpy_element_atomic_8
+ ; CHECK: __llvm_memcpy_element_unordered_atomic_8
}
define i8* @test_memcpy16(i8* %P, i8* %Q) {
; CHECK: test_memcpy16
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 16 %P, i8* align 16 %Q, i64 16, i32 16)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 16 %P, i8* align 16 %Q, i32 16, i32 16)
ret i8* %P
+ ; 3rd arg (%edx) -- length
; CHECK-DAG: movl $16, %edx
- ; CHECK-DAG: movl $16, %ecx
- ; CHECK: __llvm_memcpy_element_atomic_16
+ ; CHECK: __llvm_memcpy_element_unordered_atomic_16
}
define void @test_memcpy_args(i8** %Storage) {
@@ -51,18 +51,15 @@ define void @test_memcpy_args(i8** %Storage) {
%Src.addr = getelementptr i8*, i8** %Storage, i64 1
%Src = load i8*, i8** %Src.addr
- ; First argument
+ ; 1st arg (%rdi)
; CHECK-DAG: movq (%rdi), [[REG1:%r.+]]
; CHECK-DAG: movq [[REG1]], %rdi
- ; Second argument
+ ; 2nd arg (%rsi)
; CHECK-DAG: movq 8(%rdi), %rsi
- ; Third argument
+ ; 3rd arg (%edx) -- length
; CHECK-DAG: movl $4, %edx
- ; Fourth argument
- ; CHECK-DAG: movl $4, %ecx
- ; CHECK: __llvm_memcpy_element_atomic_4
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dst, i8* align 4 %Src, i64 4, i32 4)
- ret void
+ ; CHECK: __llvm_memcpy_element_unordered_atomic_4
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %Dst, i8* align 4 %Src, i32 4, i32 4) ret void
}
-declare void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* nocapture, i8* nocapture, i64, i32) nounwind
+declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind
diff --git a/test/CodeGen/X86/fast-isel-select-sse.ll b/test/CodeGen/X86/fast-isel-select-sse.ll
index 499fe5ba54a2..1b6bb36b77c8 100644
--- a/test/CodeGen/X86/fast-isel-select-sse.ll
+++ b/test/CodeGen/X86/fast-isel-select-sse.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs | FileCheck %s --check-prefix=SSE
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs -fast-isel -fast-isel-abort=1 | FileCheck %s --check-prefix=SSE
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -verify-machineinstrs -mattr=avx | FileCheck %s --check-prefix=AVX
@@ -29,7 +29,6 @@ define float @select_fcmp_oeq_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp oeq float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -56,7 +55,6 @@ define double @select_fcmp_oeq_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp oeq double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -84,7 +82,6 @@ define float @select_fcmp_ogt_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ogt float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -112,7 +109,6 @@ define double @select_fcmp_ogt_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ogt double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -140,7 +136,6 @@ define float @select_fcmp_oge_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp oge float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -168,7 +163,6 @@ define double @select_fcmp_oge_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp oge double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -195,7 +189,6 @@ define float @select_fcmp_olt_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp olt float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -222,7 +215,6 @@ define double @select_fcmp_olt_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp olt double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -249,7 +241,6 @@ define float @select_fcmp_ole_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ole float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -276,7 +267,6 @@ define double @select_fcmp_ole_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ole double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -303,7 +293,6 @@ define float @select_fcmp_ord_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ord float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -330,7 +319,6 @@ define double @select_fcmp_ord_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ord double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -357,7 +345,6 @@ define float @select_fcmp_uno_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp uno float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -384,7 +371,6 @@ define double @select_fcmp_uno_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp uno double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -411,7 +397,6 @@ define float @select_fcmp_ugt_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ugt float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -438,7 +423,6 @@ define double @select_fcmp_ugt_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ugt double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -465,7 +449,6 @@ define float @select_fcmp_uge_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp uge float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -492,7 +475,6 @@ define double @select_fcmp_uge_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp uge double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -520,7 +502,6 @@ define float @select_fcmp_ult_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ult float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -548,7 +529,6 @@ define double @select_fcmp_ult_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ult double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -576,7 +556,6 @@ define float @select_fcmp_ule_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ule float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -604,7 +583,6 @@ define double @select_fcmp_ule_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp ule double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
@@ -631,7 +609,6 @@ define float @select_fcmp_une_f32(float %a, float %b, float %c, float %d) {
; AVX512-NEXT: vmovss %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovaps %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp une float %a, %b
%2 = select i1 %1, float %c, float %d
ret float %2
@@ -658,7 +635,6 @@ define double @select_fcmp_une_f64(double %a, double %b, double %c, double %d) {
; AVX512-NEXT: vmovsd %xmm2, %xmm0, %xmm3 {%k1}
; AVX512-NEXT: vmovapd %xmm3, %xmm0
; AVX512-NEXT: retq
-;
%1 = fcmp une double %a, %b
%2 = select i1 %1, double %c, double %d
ret double %2
diff --git a/test/CodeGen/X86/fp-logic-replace.ll b/test/CodeGen/X86/fp-logic-replace.ll
index 308b42e10caa..e62b2f3db237 100644
--- a/test/CodeGen/X86/fp-logic-replace.ll
+++ b/test/CodeGen/X86/fp-logic-replace.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -show-mc-encoding -mattr=+sse2 | FileCheck %s --check-prefix=SSE
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -show-mc-encoding -mattr=+avx | FileCheck %s --check-prefix=AVX
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -show-mc-encoding -mattr=+avx512dq,+avx512vl | FileCheck %s --check-prefix=AVX512DQ
diff --git a/test/CodeGen/X86/fp-logic.ll b/test/CodeGen/X86/fp-logic.ll
index 973e0644b4e9..976470a83030 100644
--- a/test/CodeGen/X86/fp-logic.ll
+++ b/test/CodeGen/X86/fp-logic.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=sse2 < %s | FileCheck %s
; PR22428: https://llvm.org/bugs/show_bug.cgi?id=22428
@@ -22,7 +22,6 @@ define i32 @f1(float %x, i32 %y) {
; CHECK-NEXT: movd %xmm0, %eax
; CHECK-NEXT: andl %edi, %eax
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 %bc1, %y
ret i32 %and
@@ -36,7 +35,6 @@ define i32 @f2(float %x, i32 %y) {
; CHECK-NEXT: movd %xmm0, %eax
; CHECK-NEXT: andl %edi, %eax
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 %y, %bc1
ret i32 %and
@@ -50,7 +48,6 @@ define i32 @f3(float %x) {
; CHECK-NEXT: movd %xmm0, %eax
; CHECK-NEXT: andl $1, %eax
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 %bc1, 1
ret i32 %and
@@ -64,7 +61,6 @@ define i32 @f4(float %x) {
; CHECK-NEXT: movd %xmm0, %eax
; CHECK-NEXT: andl $2, %eax
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 2, %bc1
ret i32 %and
@@ -78,7 +74,6 @@ define float @f5(float %x, i32 %y) {
; CHECK-NEXT: movd %edi, %xmm1
; CHECK-NEXT: pand %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 %bc1, %y
%bc2 = bitcast i32 %and to float
@@ -93,7 +88,6 @@ define float @f6(float %x, i32 %y) {
; CHECK-NEXT: movd %edi, %xmm1
; CHECK-NEXT: pand %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 %y, %bc1
%bc2 = bitcast i32 %and to float
@@ -108,7 +102,6 @@ define float @f7(float %x) {
; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 %bc1, 3
%bc2 = bitcast i32 %and to float
@@ -123,7 +116,6 @@ define float @f8(float %x) {
; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 4, %bc1
%bc2 = bitcast i32 %and to float
@@ -138,7 +130,6 @@ define i32 @f9(float %x, float %y) {
; CHECK-NEXT: pand %xmm1, %xmm0
; CHECK-NEXT: movd %xmm0, %eax
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%bc2 = bitcast float %y to i32
%and = and i32 %bc1, %bc2
@@ -152,7 +143,6 @@ define float @f10(float %x, float %y) {
; CHECK: # BB#0:
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%bc2 = bitcast float %y to i32
%and = and i32 %bc1, %bc2
@@ -165,7 +155,6 @@ define float @or(float %x, float %y) {
; CHECK: # BB#0:
; CHECK-NEXT: orps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%bc2 = bitcast float %y to i32
%and = or i32 %bc1, %bc2
@@ -178,7 +167,6 @@ define float @xor(float %x, float %y) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%bc2 = bitcast float %y to i32
%and = xor i32 %bc1, %bc2
@@ -192,7 +180,6 @@ define float @f7_or(float %x) {
; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; CHECK-NEXT: orps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = or i32 %bc1, 3
%bc2 = bitcast i32 %and to float
@@ -205,7 +192,6 @@ define float @f7_xor(float %x) {
; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; CHECK-NEXT: xorps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = xor i32 %bc1, 3
%bc2 = bitcast i32 %and to float
@@ -219,7 +205,6 @@ define double @doubles(double %x, double %y) {
; CHECK: # BB#0:
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast double %x to i64
%bc2 = bitcast double %y to i64
%and = and i64 %bc1, %bc2
@@ -233,7 +218,6 @@ define double @f7_double(double %x) {
; CHECK-NEXT: movsd {{.*#+}} xmm1 = mem[0],zero
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast double %x to i64
%and = and i64 %bc1, 3
%bc2 = bitcast i64 %and to double
@@ -250,7 +234,6 @@ define float @movmsk(float %x) {
; CHECK-NEXT: movss {{.*#+}} xmm1 = mem[0],zero,zero,zero
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%and = and i32 %bc1, 2147483648
%bc2 = bitcast i32 %and to float
@@ -262,7 +245,6 @@ define double @bitcast_fabs(double %x) {
; CHECK: # BB#0:
; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast double %x to i64
%and = and i64 %bc1, 9223372036854775807
%bc2 = bitcast i64 %and to double
@@ -274,7 +256,6 @@ define float @bitcast_fneg(float %x) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast float %x to i32
%xor = xor i32 %bc1, 2147483648
%bc2 = bitcast i32 %xor to float
@@ -286,7 +267,6 @@ define <2 x double> @bitcast_fabs_vec(<2 x double> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast <2 x double> %x to <2 x i64>
%and = and <2 x i64> %bc1, <i64 9223372036854775807, i64 9223372036854775807>
%bc2 = bitcast <2 x i64> %and to <2 x double>
@@ -298,7 +278,6 @@ define <4 x float> @bitcast_fneg_vec(<4 x float> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%bc1 = bitcast <4 x float> %x to <4 x i32>
%xor = xor <4 x i32> %bc1, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648>
%bc2 = bitcast <4 x i32> %xor to <4 x float>
diff --git a/test/CodeGen/X86/fp-select-cmp-and.ll b/test/CodeGen/X86/fp-select-cmp-and.ll
index e012809cf480..651d7a3351c6 100644
--- a/test/CodeGen/X86/fp-select-cmp-and.ll
+++ b/test/CodeGen/X86/fp-select-cmp-and.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.2 | FileCheck %s
define double @test1(double %a, double %b, double %eps) {
@@ -7,7 +7,6 @@ define double @test1(double %a, double %b, double %eps) {
; CHECK-NEXT: cmpltsd %xmm2, %xmm0
; CHECK-NEXT: andpd %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp olt double %a, %eps
%cond = select i1 %cmp, double %b, double 0.000000e+00
ret double %cond
@@ -19,7 +18,6 @@ define double @test2(double %a, double %b, double %eps) {
; CHECK-NEXT: cmplesd %xmm2, %xmm0
; CHECK-NEXT: andpd %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ole double %a, %eps
%cond = select i1 %cmp, double %b, double 0.000000e+00
ret double %cond
@@ -32,7 +30,6 @@ define double @test3(double %a, double %b, double %eps) {
; CHECK-NEXT: andpd %xmm1, %xmm2
; CHECK-NEXT: movapd %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ogt double %a, %eps
%cond = select i1 %cmp, double %b, double 0.000000e+00
ret double %cond
@@ -45,7 +42,6 @@ define double @test4(double %a, double %b, double %eps) {
; CHECK-NEXT: andpd %xmm1, %xmm2
; CHECK-NEXT: movapd %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp oge double %a, %eps
%cond = select i1 %cmp, double %b, double 0.000000e+00
ret double %cond
@@ -57,7 +53,6 @@ define double @test5(double %a, double %b, double %eps) {
; CHECK-NEXT: cmpltsd %xmm2, %xmm0
; CHECK-NEXT: andnpd %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp olt double %a, %eps
%cond = select i1 %cmp, double 0.000000e+00, double %b
ret double %cond
@@ -69,7 +64,6 @@ define double @test6(double %a, double %b, double %eps) {
; CHECK-NEXT: cmplesd %xmm2, %xmm0
; CHECK-NEXT: andnpd %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ole double %a, %eps
%cond = select i1 %cmp, double 0.000000e+00, double %b
ret double %cond
@@ -82,7 +76,6 @@ define double @test7(double %a, double %b, double %eps) {
; CHECK-NEXT: andnpd %xmm1, %xmm2
; CHECK-NEXT: movapd %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ogt double %a, %eps
%cond = select i1 %cmp, double 0.000000e+00, double %b
ret double %cond
@@ -95,7 +88,6 @@ define double @test8(double %a, double %b, double %eps) {
; CHECK-NEXT: andnpd %xmm1, %xmm2
; CHECK-NEXT: movapd %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp oge double %a, %eps
%cond = select i1 %cmp, double 0.000000e+00, double %b
ret double %cond
@@ -107,7 +99,6 @@ define float @test9(float %a, float %b, float %eps) {
; CHECK-NEXT: cmpltss %xmm2, %xmm0
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp olt float %a, %eps
%cond = select i1 %cmp, float %b, float 0.000000e+00
ret float %cond
@@ -119,7 +110,6 @@ define float @test10(float %a, float %b, float %eps) {
; CHECK-NEXT: cmpless %xmm2, %xmm0
; CHECK-NEXT: andps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ole float %a, %eps
%cond = select i1 %cmp, float %b, float 0.000000e+00
ret float %cond
@@ -132,7 +122,6 @@ define float @test11(float %a, float %b, float %eps) {
; CHECK-NEXT: andps %xmm1, %xmm2
; CHECK-NEXT: movaps %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ogt float %a, %eps
%cond = select i1 %cmp, float %b, float 0.000000e+00
ret float %cond
@@ -145,7 +134,6 @@ define float @test12(float %a, float %b, float %eps) {
; CHECK-NEXT: andps %xmm1, %xmm2
; CHECK-NEXT: movaps %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp oge float %a, %eps
%cond = select i1 %cmp, float %b, float 0.000000e+00
ret float %cond
@@ -157,7 +145,6 @@ define float @test13(float %a, float %b, float %eps) {
; CHECK-NEXT: cmpltss %xmm2, %xmm0
; CHECK-NEXT: andnps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp olt float %a, %eps
%cond = select i1 %cmp, float 0.000000e+00, float %b
ret float %cond
@@ -169,7 +156,6 @@ define float @test14(float %a, float %b, float %eps) {
; CHECK-NEXT: cmpless %xmm2, %xmm0
; CHECK-NEXT: andnps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ole float %a, %eps
%cond = select i1 %cmp, float 0.000000e+00, float %b
ret float %cond
@@ -182,7 +168,6 @@ define float @test15(float %a, float %b, float %eps) {
; CHECK-NEXT: andnps %xmm1, %xmm2
; CHECK-NEXT: movaps %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp ogt float %a, %eps
%cond = select i1 %cmp, float 0.000000e+00, float %b
ret float %cond
@@ -195,7 +180,6 @@ define float @test16(float %a, float %b, float %eps) {
; CHECK-NEXT: andnps %xmm1, %xmm2
; CHECK-NEXT: movaps %xmm2, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp oge float %a, %eps
%cond = select i1 %cmp, float 0.000000e+00, float %b
ret float %cond
@@ -210,7 +194,6 @@ define float @test17(float %a, float %b, float %c, float %eps) {
; CHECK-NEXT: orps %xmm2, %xmm3
; CHECK-NEXT: movaps %xmm3, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp oge float %a, %eps
%cond = select i1 %cmp, float %c, float %b
ret float %cond
@@ -225,7 +208,6 @@ define double @test18(double %a, double %b, double %c, double %eps) {
; CHECK-NEXT: orpd %xmm2, %xmm3
; CHECK-NEXT: movapd %xmm3, %xmm0
; CHECK-NEXT: retq
-;
%cmp = fcmp oge double %a, %eps
%cond = select i1 %cmp, double %c, double %b
ret double %cond
diff --git a/test/CodeGen/X86/immediate_merging64.ll b/test/CodeGen/X86/immediate_merging64.ll
index ea8ace12a868..4bc9d4af6440 100644
--- a/test/CodeGen/X86/immediate_merging64.ll
+++ b/test/CodeGen/X86/immediate_merging64.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
; Check that multiple instances of 64-bit constants encodable as
@@ -14,7 +14,6 @@ define i1 @imm_multiple_users(i64 %a, i64* %b) optsize {
; CHECK-NEXT: cmpq %rax, %rdi
; CHECK-NEXT: sete %al
; CHECK-NEXT: retq
-;
store i64 -1, i64* %b, align 8
%cmp = icmp eq i64 %a, -1
ret i1 %cmp
@@ -32,7 +31,6 @@ define void @memset_zero(i8* noalias nocapture %D) optsize {
; CHECK-NEXT: movq %rax, 7(%rdi)
; CHECK-NEXT: movq %rax, (%rdi)
; CHECK-NEXT: retq
-;
tail call void @llvm.memset.p0i8.i64(i8* %D, i8 0, i64 15, i32 1, i1 false)
ret void
}
diff --git a/test/CodeGen/X86/lea-opt-with-debug.mir b/test/CodeGen/X86/lea-opt-with-debug.mir
index 0a477706df15..03a745888b5a 100644
--- a/test/CodeGen/X86/lea-opt-with-debug.mir
+++ b/test/CodeGen/X86/lea-opt-with-debug.mir
@@ -49,7 +49,7 @@
!5 = !{i32 2, !"Dwarf Version", i32 4}
!6 = !{i32 2, !"Debug Info Version", i32 3}
!7 = !{i32 1, !"PIC Level", i32 2}
- !8 = !DIExpression(DW_OP_plus, 8, DW_OP_stack_value)
+ !8 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_stack_value)
!9 = distinct !DISubprogram(name: "fn1", scope: !1, file: !1, line: 7, type: !10, isLocal: false, isDefinition: true, scopeLine: 7, isOptimized: true, unit: !0, variables: !11)
!10 = !DISubroutineType(types: !3)
!11 = !{!12}
diff --git a/test/CodeGen/X86/loop-search.ll b/test/CodeGen/X86/loop-search.ll
index 6b29a726fc1f..fda4ecec0e6a 100644
--- a/test/CodeGen/X86/loop-search.ll
+++ b/test/CodeGen/X86/loop-search.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s
; This test comes from PR27136
@@ -35,7 +35,6 @@ define zeroext i1 @search(i32 %needle, i32* nocapture readonly %haystack, i32 %c
; CHECK-NEXT: movb $1, %al
; CHECK-NEXT: ## kill: %AL<def> %AL<kill> %EAX<kill>
; CHECK-NEXT: retq
-;
entry:
%cmp5 = icmp sgt i32 %count, 0
br i1 %cmp5, label %for.body.preheader, label %cleanup
diff --git a/test/CodeGen/X86/mask-negated-bool.ll b/test/CodeGen/X86/mask-negated-bool.ll
index c5c121c52966..779641cee7d2 100644
--- a/test/CodeGen/X86/mask-negated-bool.ll
+++ b/test/CodeGen/X86/mask-negated-bool.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
define i32 @mask_negated_zext_bool1(i1 %x) {
@@ -7,7 +7,6 @@ define i32 @mask_negated_zext_bool1(i1 %x) {
; CHECK-NEXT: andl $1, %edi
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-;
%ext = zext i1 %x to i32
%neg = sub i32 0, %ext
%and = and i32 %neg, 1
@@ -19,7 +18,6 @@ define i32 @mask_negated_zext_bool2(i1 zeroext %x) {
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: retq
-;
%ext = zext i1 %x to i32
%neg = sub i32 0, %ext
%and = and i32 %neg, 1
@@ -31,7 +29,6 @@ define <4 x i32> @mask_negated_zext_bool_vec(<4 x i1> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%ext = zext <4 x i1> %x to <4 x i32>
%neg = sub <4 x i32> zeroinitializer, %ext
%and = and <4 x i32> %neg, <i32 1, i32 1, i32 1, i32 1>
@@ -44,7 +41,6 @@ define i32 @mask_negated_sext_bool1(i1 %x) {
; CHECK-NEXT: andl $1, %edi
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-;
%ext = sext i1 %x to i32
%neg = sub i32 0, %ext
%and = and i32 %neg, 1
@@ -56,7 +52,6 @@ define i32 @mask_negated_sext_bool2(i1 zeroext %x) {
; CHECK: # BB#0:
; CHECK-NEXT: movzbl %dil, %eax
; CHECK-NEXT: retq
-;
%ext = sext i1 %x to i32
%neg = sub i32 0, %ext
%and = and i32 %neg, 1
@@ -68,7 +63,6 @@ define <4 x i32> @mask_negated_sext_bool_vec(<4 x i1> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%ext = sext <4 x i1> %x to <4 x i32>
%neg = sub <4 x i32> zeroinitializer, %ext
%and = and <4 x i32> %neg, <i32 1, i32 1, i32 1, i32 1>
diff --git a/test/CodeGen/X86/memset-2.ll b/test/CodeGen/X86/memset-2.ll
index a02ef29ca6b3..1ac972048f12 100644
--- a/test/CodeGen/X86/memset-2.ll
+++ b/test/CodeGen/X86/memset-2.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=i386-apple-darwin9 -mcpu=yonah < %s | FileCheck %s
define fastcc void @t1() nounwind {
@@ -10,7 +10,6 @@ define fastcc void @t1() nounwind {
; CHECK-NEXT: pushl $0
; CHECK-NEXT: calll _memset
; CHECK-NEXT: addl $16, %esp
-;
entry:
call void @llvm.memset.p0i8.i32(i8* null, i8 0, i32 188, i32 1, i1 false)
unreachable
@@ -23,7 +22,6 @@ define fastcc void @t2(i8 signext %c) nounwind {
; CHECK-NEXT: movl %ecx, {{[0-9]+}}(%esp)
; CHECK-NEXT: movl $76, {{[0-9]+}}(%esp)
; CHECK-NEXT: calll _memset
-;
entry:
call void @llvm.memset.p0i8.i32(i8* undef, i8 %c, i32 76, i32 1, i1 false)
unreachable
@@ -40,7 +38,6 @@ define void @t3(i8* nocapture %s, i8 %a) nounwind {
; CHECK-NEXT: movl %ecx, 4(%eax)
; CHECK-NEXT: movl %ecx, (%eax)
; CHECK-NEXT: retl
-;
entry:
tail call void @llvm.memset.p0i8.i32(i8* %s, i8 %a, i32 8, i32 1, i1 false)
ret void
@@ -58,7 +55,6 @@ define void @t4(i8* nocapture %s, i8 %a) nounwind {
; CHECK-NEXT: movw %cx, 12(%eax)
; CHECK-NEXT: movb %cl, 14(%eax)
; CHECK-NEXT: retl
-;
entry:
tail call void @llvm.memset.p0i8.i32(i8* %s, i8 %a, i32 15, i32 1, i1 false)
ret void
diff --git a/test/CodeGen/X86/memset-nonzero.ll b/test/CodeGen/X86/memset-nonzero.ll
index 769fe87880b0..13258fd81de5 100644
--- a/test/CodeGen/X86/memset-nonzero.ll
+++ b/test/CodeGen/X86/memset-nonzero.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-unknown-unknown < %s -mattr=sse | FileCheck %s --check-prefix=SSE
; RUN: llc -mtriple=x86_64-unknown-unknown < %s -mattr=sse2 | FileCheck %s --check-prefix=SSE
; RUN: llc -mtriple=x86_64-unknown-unknown < %s -mattr=sse2,-slow-unaligned-mem-16 | FileCheck %s --check-prefix=SSE2FAST
@@ -26,7 +26,6 @@ define void @memset_16_nonzero_bytes(i8* %x) {
; AVX-NEXT: vmovaps {{.*#+}} xmm0 = [42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42]
; AVX-NEXT: vmovups %xmm0, (%rdi)
; AVX-NEXT: retq
-;
%call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 16, i64 -1)
ret void
}
@@ -54,7 +53,6 @@ define void @memset_32_nonzero_bytes(i8* %x) {
; AVX-NEXT: vmovups %ymm0, (%rdi)
; AVX-NEXT: vzeroupper
; AVX-NEXT: retq
-;
%call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 32, i64 -1)
ret void
}
@@ -89,7 +87,6 @@ define void @memset_64_nonzero_bytes(i8* %x) {
; AVX-NEXT: vmovups %ymm0, (%rdi)
; AVX-NEXT: vzeroupper
; AVX-NEXT: retq
-;
%call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 64, i64 -1)
ret void
}
@@ -138,7 +135,6 @@ define void @memset_128_nonzero_bytes(i8* %x) {
; AVX-NEXT: vmovups %ymm0, (%rdi)
; AVX-NEXT: vzeroupper
; AVX-NEXT: retq
-;
%call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 128, i64 -1)
ret void
}
@@ -189,7 +185,6 @@ define void @memset_256_nonzero_bytes(i8* %x) {
; AVX-NEXT: vmovups %ymm0, (%rdi)
; AVX-NEXT: vzeroupper
; AVX-NEXT: retq
-;
%call = tail call i8* @__memset_chk(i8* %x, i32 42, i64 256, i64 -1)
ret void
}
@@ -231,7 +226,6 @@ define void @memset_16_nonconst_bytes(i8* %x, i8 %c) {
; AVX2-NEXT: vpbroadcastb %xmm0, %xmm0
; AVX2-NEXT: vmovdqu %xmm0, (%rdi)
; AVX2-NEXT: retq
-;
tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 16, i32 1, i1 false)
ret void
}
@@ -275,7 +269,6 @@ define void @memset_32_nonconst_bytes(i8* %x, i8 %c) {
; AVX2-NEXT: vmovdqu %ymm0, (%rdi)
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
-;
tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 32, i32 1, i1 false)
ret void
}
@@ -327,7 +320,6 @@ define void @memset_64_nonconst_bytes(i8* %x, i8 %c) {
; AVX2-NEXT: vmovdqu %ymm0, (%rdi)
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
-;
tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 64, i32 1, i1 false)
ret void
}
@@ -395,7 +387,6 @@ define void @memset_128_nonconst_bytes(i8* %x, i8 %c) {
; AVX2-NEXT: vmovdqu %ymm0, (%rdi)
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
-;
tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 128, i32 1, i1 false)
ret void
}
@@ -461,7 +452,6 @@ define void @memset_256_nonconst_bytes(i8* %x, i8 %c) {
; AVX2-NEXT: vmovdqu %ymm0, (%rdi)
; AVX2-NEXT: vzeroupper
; AVX2-NEXT: retq
-;
tail call void @llvm.memset.p0i8.i64(i8* %x, i8 %c, i64 256, i32 1, i1 false)
ret void
}
diff --git a/test/CodeGen/X86/memset64-on-x86-32.ll b/test/CodeGen/X86/memset64-on-x86-32.ll
index 861cb88b0f57..a7a3c61b1392 100644
--- a/test/CodeGen/X86/memset64-on-x86-32.ll
+++ b/test/CodeGen/X86/memset64-on-x86-32.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=i386-unknown-unknown -mattr=sse4.2 | FileCheck %s --check-prefix=FAST
; RUN: llc < %s -mtriple=i386-unknown-unknown -mattr=ssse3 | FileCheck %s --check-prefix=SLOW_32
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=ssse3 | FileCheck %s --check-prefix=SLOW_64
@@ -51,7 +51,6 @@ define void @bork() nounwind {
; SLOW_64-NEXT: movq $0, 8
; SLOW_64-NEXT: movq $0, 0
; SLOW_64-NEXT: retq
-;
call void @llvm.memset.p0i8.i64(i8* null, i8 0, i64 80, i32 4, i1 false)
ret void
}
diff --git a/test/CodeGen/X86/negate-i1.ll b/test/CodeGen/X86/negate-i1.ll
index f1678a1b22ff..13f831fd37b7 100644
--- a/test/CodeGen/X86/negate-i1.ll
+++ b/test/CodeGen/X86/negate-i1.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64
; RUN: llc < %s -mtriple=i386-unknown-unknown | FileCheck %s --check-prefix=X32
@@ -16,7 +16,6 @@ define i8 @select_i8_neg1_or_0(i1 %a) {
; X32-NEXT: andb $1, %al
; X32-NEXT: negb %al
; X32-NEXT: retl
-;
%b = sext i1 %a to i8
ret i8 %b
}
@@ -33,7 +32,6 @@ define i8 @select_i8_neg1_or_0_zeroext(i1 zeroext %a) {
; X32-NEXT: movb {{[0-9]+}}(%esp), %al
; X32-NEXT: negb %al
; X32-NEXT: retl
-;
%b = sext i1 %a to i8
ret i8 %b
}
@@ -53,7 +51,6 @@ define i16 @select_i16_neg1_or_0(i1 %a) {
; X32-NEXT: negl %eax
; X32-NEXT: # kill: %AX<def> %AX<kill> %EAX<kill>
; X32-NEXT: retl
-;
%b = sext i1 %a to i16
ret i16 %b
}
@@ -72,7 +69,6 @@ define i16 @select_i16_neg1_or_0_zeroext(i1 zeroext %a) {
; X32-NEXT: negl %eax
; X32-NEXT: # kill: %AX<def> %AX<kill> %EAX<kill>
; X32-NEXT: retl
-;
%b = sext i1 %a to i16
ret i16 %b
}
@@ -91,7 +87,6 @@ define i32 @select_i32_neg1_or_0(i1 %a) {
; X32-NEXT: andl $1, %eax
; X32-NEXT: negl %eax
; X32-NEXT: retl
-;
%b = sext i1 %a to i32
ret i32 %b
}
@@ -108,7 +103,6 @@ define i32 @select_i32_neg1_or_0_zeroext(i1 zeroext %a) {
; X32-NEXT: movzbl {{[0-9]+}}(%esp), %eax
; X32-NEXT: negl %eax
; X32-NEXT: retl
-;
%b = sext i1 %a to i32
ret i32 %b
}
@@ -129,7 +123,6 @@ define i64 @select_i64_neg1_or_0(i1 %a) {
; X32-NEXT: negl %eax
; X32-NEXT: movl %eax, %edx
; X32-NEXT: retl
-;
%b = sext i1 %a to i64
ret i64 %b
}
@@ -147,7 +140,6 @@ define i64 @select_i64_neg1_or_0_zeroext(i1 zeroext %a) {
; X32-NEXT: negl %eax
; X32-NEXT: movl %eax, %edx
; X32-NEXT: retl
-;
%b = sext i1 %a to i64
ret i64 %b
}
diff --git a/test/CodeGen/X86/negate-shift.ll b/test/CodeGen/X86/negate-shift.ll
index 54ffc8e71e07..cbe2f9456fa1 100644
--- a/test/CodeGen/X86/negate-shift.ll
+++ b/test/CodeGen/X86/negate-shift.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64
define i32 @neg_lshr_signbit(i32 %x) {
@@ -7,7 +7,6 @@ define i32 @neg_lshr_signbit(i32 %x) {
; X64-NEXT: sarl $31, %edi
; X64-NEXT: movl %edi, %eax
; X64-NEXT: retq
-;
%sh = lshr i32 %x, 31
%neg = sub i32 0, %sh
ret i32 %neg
@@ -19,7 +18,6 @@ define i64 @neg_ashr_signbit(i64 %x) {
; X64-NEXT: shrq $63, %rdi
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: retq
-;
%sh = ashr i64 %x, 63
%neg = sub i64 0, %sh
ret i64 %neg
@@ -30,7 +28,6 @@ define <4 x i32> @neg_ashr_signbit_vec(<4 x i32> %x) {
; X64: # BB#0:
; X64-NEXT: psrld $31, %xmm0
; X64-NEXT: retq
-;
%sh = ashr <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
%neg = sub <4 x i32> zeroinitializer, %sh
ret <4 x i32> %neg
@@ -41,7 +38,6 @@ define <8 x i16> @neg_lshr_signbit_vec(<8 x i16> %x) {
; X64: # BB#0:
; X64-NEXT: psraw $15, %xmm0
; X64-NEXT: retq
-;
%sh = lshr <8 x i16> %x, <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15>
%neg = sub <8 x i16> zeroinitializer, %sh
ret <8 x i16> %neg
diff --git a/test/CodeGen/X86/negate.ll b/test/CodeGen/X86/negate.ll
index 6f07378e0e46..5bdb11479afc 100644
--- a/test/CodeGen/X86/negate.ll
+++ b/test/CodeGen/X86/negate.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
define i32 @negate_nuw(i32 %x) {
@@ -6,7 +6,6 @@ define i32 @negate_nuw(i32 %x) {
; CHECK: # BB#0:
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: retq
-;
%neg = sub nuw i32 0, %x
ret i32 %neg
}
@@ -16,7 +15,6 @@ define <4 x i32> @negate_nuw_vec(<4 x i32> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%neg = sub nuw <4 x i32> zeroinitializer, %x
ret <4 x i32> %neg
}
@@ -26,7 +24,6 @@ define i8 @negate_zero_or_minsigned_nsw(i8 %x) {
; CHECK: # BB#0:
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: retq
-;
%signbit = and i8 %x, 128
%neg = sub nsw i8 0, %signbit
ret i8 %neg
@@ -37,7 +34,6 @@ define <4 x i32> @negate_zero_or_minsigned_nsw_vec(<4 x i32> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%signbit = shl <4 x i32> %x, <i32 31, i32 31, i32 31, i32 31>
%neg = sub nsw <4 x i32> zeroinitializer, %signbit
ret <4 x i32> %neg
@@ -49,7 +45,6 @@ define i8 @negate_zero_or_minsigned(i8 %x) {
; CHECK-NEXT: shlb $7, %dil
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-;
%signbit = shl i8 %x, 7
%neg = sub i8 0, %signbit
ret i8 %neg
@@ -60,7 +55,6 @@ define <4 x i32> @negate_zero_or_minsigned_vec(<4 x i32> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%signbit = and <4 x i32> %x, <i32 2147483648, i32 2147483648, i32 2147483648, i32 2147483648>
%neg = sub <4 x i32> zeroinitializer, %signbit
ret <4 x i32> %neg
diff --git a/test/CodeGen/X86/negative-sin.ll b/test/CodeGen/X86/negative-sin.ll
index bc38021b5620..94369e3e8d0f 100644
--- a/test/CodeGen/X86/negative-sin.ll
+++ b/test/CodeGen/X86/negative-sin.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=avx | FileCheck %s
declare double @sin(double %f)
@@ -16,7 +16,6 @@ define double @strict(double %e) nounwind {
; CHECK-NEXT: vsubsd %xmm0, %xmm1, %xmm0
; CHECK-NEXT: popq %rax
; CHECK-NEXT: retq
-;
%f = fsub double 0.0, %e
%g = call double @sin(double %f) readonly
%h = fsub double 0.0, %g
@@ -29,8 +28,7 @@ define double @strict(double %e) nounwind {
define double @fast(double %e) nounwind {
; CHECK-LABEL: fast:
; CHECK: # BB#0:
-; CHECK-NEXT: jmp sin
-;
+; CHECK-NEXT: jmp sin # TAILCALL
%f = fsub fast double 0.0, %e
%g = call double @sin(double %f) readonly
%h = fsub fast double 0.0, %g
@@ -42,8 +40,7 @@ define double @fast(double %e) nounwind {
define double @nsz(double %e) nounwind {
; CHECK-LABEL: nsz:
; CHECK: # BB#0:
-; CHECK-NEXT: jmp sin
-;
+; CHECK-NEXT: jmp sin # TAILCALL
%f = fsub nsz double 0.0, %e
%g = call double @sin(double %f) readonly
%h = fsub nsz double 0.0, %g
@@ -62,7 +59,6 @@ define double @semi_strict1(double %e) nounwind {
; CHECK-NEXT: vxorpd {{.*}}(%rip), %xmm0, %xmm0
; CHECK-NEXT: popq %rax
; CHECK-NEXT: retq
-;
%f = fsub double 0.0, %e
%g = call double @sin(double %f) readonly
%h = fsub nsz double 0.0, %g
@@ -80,7 +76,6 @@ define double @semi_strict2(double %e) nounwind {
; CHECK-NEXT: vaddsd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: popq %rax
; CHECK-NEXT: retq
-;
%f = fsub nsz double 0.0, %e
%g = call double @sin(double %f) readonly
%h = fsub double 0.0, %g
@@ -93,8 +88,7 @@ define double @semi_strict2(double %e) nounwind {
define double @fn_attr(double %e) nounwind #0 {
; CHECK-LABEL: fn_attr:
; CHECK: # BB#0:
-; CHECK-NEXT: jmp sin
-;
+; CHECK-NEXT: jmp sin # TAILCALL
%f = fsub double 0.0, %e
%g = call double @sin(double %f) readonly
%h = fsub double 0.0, %g
diff --git a/test/CodeGen/X86/no-sse2-avg.ll b/test/CodeGen/X86/no-sse2-avg.ll
index 0ed0a7f74cb3..e4b97c17047c 100644
--- a/test/CodeGen/X86/no-sse2-avg.ll
+++ b/test/CodeGen/X86/no-sse2-avg.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; REQUIRES: asserts
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-sse2 | FileCheck %s
@@ -23,7 +23,6 @@ define <16 x i8> @PR27973() {
; CHECK-NEXT: movb $0, (%rdi)
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: retq
-;
%t0 = zext <16 x i8> zeroinitializer to <16 x i32>
%t1 = add nuw nsw <16 x i32> %t0, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
%t2 = lshr <16 x i32> %t1, <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>
diff --git a/test/CodeGen/X86/not-and-simplify.ll b/test/CodeGen/X86/not-and-simplify.ll
index 83b2be83d552..87aa10a6e296 100644
--- a/test/CodeGen/X86/not-and-simplify.ll
+++ b/test/CodeGen/X86/not-and-simplify.ll
@@ -1,5 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=-bmi | FileCheck %s --check-prefix=ALL --check-prefix=NO_BMI
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=ALL --check-prefix=BMI
diff --git a/test/CodeGen/X86/pr13577.ll b/test/CodeGen/X86/pr13577.ll
index 1b1622513ea6..665df2c183bf 100644
--- a/test/CodeGen/X86/pr13577.ll
+++ b/test/CodeGen/X86/pr13577.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-darwin | FileCheck %s
; CHECK-LABEL: LCPI0_0:
@@ -12,12 +12,11 @@ define x86_fp80 @foo(x86_fp80 %a) {
; CHECK-NEXT: fldt {{[0-9]+}}(%rsp)
; CHECK-NEXT: fstpt -{{[0-9]+}}(%rsp)
; CHECK-NEXT: testb $-128, -{{[0-9]+}}(%rsp)
-; CHECK-NEXT: flds LCPI0_0(%rip)
-; CHECK-NEXT: flds LCPI0_1(%rip)
+; CHECK-NEXT: flds {{.*}}(%rip)
+; CHECK-NEXT: flds {{.*}}(%rip)
; CHECK-NEXT: fcmovne %st(1), %st(0)
; CHECK-NEXT: fstp %st(1)
; CHECK-NEXT: retq
-;
%1 = tail call x86_fp80 @copysignl(x86_fp80 0xK7FFF8000000000000000, x86_fp80 %a) nounwind readnone
ret x86_fp80 %1
}
@@ -34,7 +33,6 @@ define float @pr26070() {
; CHECK-NEXT: shufps {{.*#+}} xmm0 = xmm0[0,0,0,0]
; CHECK-NEXT: orps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%c = call float @copysignf(float 1.0, float undef) readnone
ret float %c
}
diff --git a/test/CodeGen/X86/pr18014.ll b/test/CodeGen/X86/pr18014.ll
index bb3b9c23f1e3..cba065002d57 100644
--- a/test/CodeGen/X86/pr18014.ll
+++ b/test/CodeGen/X86/pr18014.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse4.1 | FileCheck %s
; Ensure PSRAD is generated as the condition is consumed by both PADD and
@@ -14,7 +14,6 @@ define <4 x i32> @foo(<4 x i32>* %p, <4 x i1> %cond, <4 x i32> %v1, <4 x i32> %v
; CHECK-NEXT: movaps %xmm2, (%rdi)
; CHECK-NEXT: movdqa %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%sext_cond = sext <4 x i1> %cond to <4 x i32>
%t1 = add <4 x i32> %v1, %sext_cond
%t2 = select <4 x i1> %cond, <4 x i32> %v1, <4 x i32> %v2
diff --git a/test/CodeGen/X86/pr32368.ll b/test/CodeGen/X86/pr32368.ll
new file mode 100644
index 000000000000..b0f0b123cca1
--- /dev/null
+++ b/test/CodeGen/X86/pr32368.ll
@@ -0,0 +1,153 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=CHECK --check-prefix=SSE
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=CHECK --check-prefix=AVX1
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx2 | FileCheck %s --check-prefix=CHECK --check-prefix=AVX2
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx512f | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512
+
+define <4 x float> @PR32368_128(<4 x float>) {
+; SSE-LABEL: PR32368_128:
+; SSE: # BB#0:
+; SSE-NEXT: andps {{.*}}(%rip), %xmm0
+; SSE-NEXT: addps %xmm0, %xmm0
+; SSE-NEXT: andps {{.*}}(%rip), %xmm0
+; SSE-NEXT: retq
+;
+; AVX1-LABEL: PR32368_128:
+; AVX1: # BB#0:
+; AVX1-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0
+; AVX1-NEXT: vaddps %xmm0, %xmm0, %xmm0
+; AVX1-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0
+; AVX1-NEXT: retq
+;
+; AVX2-LABEL: PR32368_128:
+; AVX2: # BB#0:
+; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %xmm1
+; AVX2-NEXT: vandps %xmm1, %xmm0, %xmm0
+; AVX2-NEXT: vaddps %xmm0, %xmm0, %xmm0
+; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %xmm1
+; AVX2-NEXT: vandps %xmm1, %xmm0, %xmm0
+; AVX2-NEXT: retq
+;
+; AVX512-LABEL: PR32368_128:
+; AVX512: # BB#0:
+; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %xmm1
+; AVX512-NEXT: vandps %xmm1, %xmm0, %xmm0
+; AVX512-NEXT: vaddps %xmm0, %xmm0, %xmm0
+; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %xmm1
+; AVX512-NEXT: vandps %xmm1, %xmm0, %xmm0
+; AVX512-NEXT: retq
+ %2 = bitcast <4 x float> %0 to <4 x i32>
+ %3 = and <4 x i32> %2, <i32 -292, i32 -292, i32 -292, i32 -292>
+ %4 = bitcast <4 x i32> %3 to <4 x float>
+ %5 = fmul <4 x float> %4, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>
+ %6 = bitcast <4 x float> %5 to <4 x i32>
+ %7 = and <4 x i32> %6, <i32 291, i32 291, i32 291, i32 291>
+ %8 = bitcast <4 x i32> %7 to <4 x float>
+ ret <4 x float> %8
+}
+
+define <8 x float> @PR32368_256(<8 x float>) {
+; SSE-LABEL: PR32368_256:
+; SSE: # BB#0:
+; SSE-NEXT: movaps {{.*#+}} xmm2 = [4294967004,4294967004,4294967004,4294967004]
+; SSE-NEXT: andps %xmm2, %xmm0
+; SSE-NEXT: andps %xmm2, %xmm1
+; SSE-NEXT: addps %xmm1, %xmm1
+; SSE-NEXT: addps %xmm0, %xmm0
+; SSE-NEXT: movaps {{.*#+}} xmm2 = [291,291,291,291]
+; SSE-NEXT: andps %xmm2, %xmm0
+; SSE-NEXT: andps %xmm2, %xmm1
+; SSE-NEXT: retq
+;
+; AVX1-LABEL: PR32368_256:
+; AVX1: # BB#0:
+; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0
+; AVX1-NEXT: vaddps %ymm0, %ymm0, %ymm0
+; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0
+; AVX1-NEXT: retq
+;
+; AVX2-LABEL: PR32368_256:
+; AVX2: # BB#0:
+; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm1
+; AVX2-NEXT: vandps %ymm1, %ymm0, %ymm0
+; AVX2-NEXT: vaddps %ymm0, %ymm0, %ymm0
+; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm1
+; AVX2-NEXT: vandps %ymm1, %ymm0, %ymm0
+; AVX2-NEXT: retq
+;
+; AVX512-LABEL: PR32368_256:
+; AVX512: # BB#0:
+; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %ymm1
+; AVX512-NEXT: vandps %ymm1, %ymm0, %ymm0
+; AVX512-NEXT: vaddps %ymm0, %ymm0, %ymm0
+; AVX512-NEXT: vbroadcastss {{.*}}(%rip), %ymm1
+; AVX512-NEXT: vandps %ymm1, %ymm0, %ymm0
+; AVX512-NEXT: retq
+ %2 = bitcast <8 x float> %0 to <8 x i32>
+ %3 = and <8 x i32> %2, <i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292>
+ %4 = bitcast <8 x i32> %3 to <8 x float>
+ %5 = fmul <8 x float> %4, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>
+ %6 = bitcast <8 x float> %5 to <8 x i32>
+ %7 = and <8 x i32> %6, <i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291>
+ %8 = bitcast <8 x i32> %7 to <8 x float>
+ ret <8 x float> %8
+}
+
+define <16 x float> @PR32368_512(<16 x float>) {
+; SSE-LABEL: PR32368_512:
+; SSE: # BB#0:
+; SSE-NEXT: movaps {{.*#+}} xmm4 = [4294967004,4294967004,4294967004,4294967004]
+; SSE-NEXT: andps %xmm4, %xmm0
+; SSE-NEXT: andps %xmm4, %xmm1
+; SSE-NEXT: andps %xmm4, %xmm2
+; SSE-NEXT: andps %xmm4, %xmm3
+; SSE-NEXT: addps %xmm3, %xmm3
+; SSE-NEXT: addps %xmm2, %xmm2
+; SSE-NEXT: addps %xmm1, %xmm1
+; SSE-NEXT: addps %xmm0, %xmm0
+; SSE-NEXT: movaps {{.*#+}} xmm4 = [291,291,291,291]
+; SSE-NEXT: andps %xmm4, %xmm0
+; SSE-NEXT: andps %xmm4, %xmm1
+; SSE-NEXT: andps %xmm4, %xmm2
+; SSE-NEXT: andps %xmm4, %xmm3
+; SSE-NEXT: retq
+;
+; AVX1-LABEL: PR32368_512:
+; AVX1: # BB#0:
+; AVX1-NEXT: vmovaps {{.*#+}} ymm2 = [4294967004,4294967004,4294967004,4294967004,4294967004,4294967004,4294967004,4294967004]
+; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm0
+; AVX1-NEXT: vandps %ymm2, %ymm1, %ymm1
+; AVX1-NEXT: vaddps %ymm1, %ymm1, %ymm1
+; AVX1-NEXT: vaddps %ymm0, %ymm0, %ymm0
+; AVX1-NEXT: vmovaps {{.*#+}} ymm2 = [291,291,291,291,291,291,291,291]
+; AVX1-NEXT: vandps %ymm2, %ymm0, %ymm0
+; AVX1-NEXT: vandps %ymm2, %ymm1, %ymm1
+; AVX1-NEXT: retq
+;
+; AVX2-LABEL: PR32368_512:
+; AVX2: # BB#0:
+; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm2
+; AVX2-NEXT: vandps %ymm2, %ymm0, %ymm0
+; AVX2-NEXT: vandps %ymm2, %ymm1, %ymm1
+; AVX2-NEXT: vaddps %ymm1, %ymm1, %ymm1
+; AVX2-NEXT: vaddps %ymm0, %ymm0, %ymm0
+; AVX2-NEXT: vbroadcastss {{.*}}(%rip), %ymm2
+; AVX2-NEXT: vandps %ymm2, %ymm0, %ymm0
+; AVX2-NEXT: vandps %ymm2, %ymm1, %ymm1
+; AVX2-NEXT: retq
+;
+; AVX512-LABEL: PR32368_512:
+; AVX512: # BB#0:
+; AVX512-NEXT: vpandd {{.*}}(%rip){1to16}, %zmm0, %zmm0
+; AVX512-NEXT: vaddps %zmm0, %zmm0, %zmm0
+; AVX512-NEXT: vpandd {{.*}}(%rip){1to16}, %zmm0, %zmm0
+; AVX512-NEXT: retq
+ %2 = bitcast <16 x float> %0 to <16 x i32>
+ %3 = and <16 x i32> %2, <i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292, i32 -292>
+ %4 = bitcast <16 x i32> %3 to <16 x float>
+ %5 = fmul <16 x float> %4, <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>
+ %6 = bitcast <16 x float> %5 to <16 x i32>
+ %7 = and <16 x i32> %6, <i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291, i32 291>
+ %8 = bitcast <16 x i32> %7 to <16 x float>
+ ret <16 x float> %8
+}
diff --git a/test/CodeGen/X86/rem.ll b/test/CodeGen/X86/rem.ll
index cc591e5ac00b..7b138f02eb4a 100644
--- a/test/CodeGen/X86/rem.ll
+++ b/test/CodeGen/X86/rem.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=i386-unknown-unknown | FileCheck %s
define i32 @test1(i32 %X) {
@@ -19,7 +19,6 @@ define i32 @test1(i32 %X) {
; CHECK-NEXT: subl %eax, %ecx
; CHECK-NEXT: movl %ecx, %eax
; CHECK-NEXT: retl
-;
%tmp1 = srem i32 %X, 255
ret i32 %tmp1
}
@@ -35,7 +34,6 @@ define i32 @test2(i32 %X) {
; CHECK-NEXT: andl $-256, %ecx
; CHECK-NEXT: subl %ecx, %eax
; CHECK-NEXT: retl
-;
%tmp1 = srem i32 %X, 256
ret i32 %tmp1
}
@@ -54,7 +52,6 @@ define i32 @test3(i32 %X) {
; CHECK-NEXT: subl %eax, %ecx
; CHECK-NEXT: movl %ecx, %eax
; CHECK-NEXT: retl
-;
%tmp1 = urem i32 %X, 255
ret i32 %tmp1
}
@@ -64,7 +61,6 @@ define i32 @test4(i32 %X) {
; CHECK: # BB#0:
; CHECK-NEXT: movzbl {{[0-9]+}}(%esp), %eax
; CHECK-NEXT: retl
-;
%tmp1 = urem i32 %X, 256
ret i32 %tmp1
}
@@ -77,8 +73,8 @@ define i32 @test5(i32 %X) nounwind readnone {
; CHECK-NEXT: idivl {{[0-9]+}}(%esp)
; CHECK-NEXT: movl %edx, %eax
; CHECK-NEXT: retl
-;
entry:
%0 = srem i32 41, %X
ret i32 %0
}
+
diff --git a/test/CodeGen/X86/sar_fold64.ll b/test/CodeGen/X86/sar_fold64.ll
index 213ca95fc78d..66ad8c3f40fa 100644
--- a/test/CodeGen/X86/sar_fold64.ll
+++ b/test/CodeGen/X86/sar_fold64.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
define i32 @shl48sar47(i64 %a) #0 {
@@ -8,7 +8,6 @@ define i32 @shl48sar47(i64 %a) #0 {
; CHECK-NEXT: addl %eax, %eax
; CHECK-NEXT: # kill: %EAX<def> %EAX<kill> %RAX<kill>
; CHECK-NEXT: retq
-;
%1 = shl i64 %a, 48
%2 = ashr exact i64 %1, 47
%3 = trunc i64 %2 to i32
@@ -22,7 +21,6 @@ define i32 @shl48sar49(i64 %a) #0 {
; CHECK-NEXT: shrq %rax
; CHECK-NEXT: # kill: %EAX<def> %EAX<kill> %RAX<kill>
; CHECK-NEXT: retq
-;
%1 = shl i64 %a, 48
%2 = ashr exact i64 %1, 49
%3 = trunc i64 %2 to i32
@@ -36,7 +34,6 @@ define i32 @shl56sar55(i64 %a) #0 {
; CHECK-NEXT: addl %eax, %eax
; CHECK-NEXT: # kill: %EAX<def> %EAX<kill> %RAX<kill>
; CHECK-NEXT: retq
-;
%1 = shl i64 %a, 56
%2 = ashr exact i64 %1, 55
%3 = trunc i64 %2 to i32
@@ -50,7 +47,6 @@ define i32 @shl56sar57(i64 %a) #0 {
; CHECK-NEXT: shrq %rax
; CHECK-NEXT: # kill: %EAX<def> %EAX<kill> %RAX<kill>
; CHECK-NEXT: retq
-;
%1 = shl i64 %a, 56
%2 = ashr exact i64 %1, 57
%3 = trunc i64 %2 to i32
@@ -64,7 +60,6 @@ define i8 @all_sign_bit_ashr(i8 %x) {
; CHECK-NEXT: negb %dil
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: retq
-;
%and = and i8 %x, 1
%neg = sub i8 0, %and
%sar = ashr i8 %neg, 6
@@ -79,7 +74,6 @@ define <4 x i32> @all_sign_bit_ashr_vec(<4 x i32> %x) {
; CHECK-NEXT: psubd %xmm0, %xmm1
; CHECK-NEXT: movdqa %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%and = and <4 x i32> %x, <i32 1, i32 1, i32 1 , i32 1>
%neg = sub <4 x i32> zeroinitializer, %and
%sar = ashr <4 x i32> %neg, <i32 1, i32 31, i32 5, i32 0>
diff --git a/test/CodeGen/X86/select-with-and-or.ll b/test/CodeGen/X86/select-with-and-or.ll
index f49da8576d18..45e4384d0fa1 100644
--- a/test/CodeGen/X86/select-with-and-or.ll
+++ b/test/CodeGen/X86/select-with-and-or.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s
define <4 x i32> @test1(<4 x float> %a, <4 x float> %b, <4 x i32> %c) {
@@ -7,7 +7,6 @@ define <4 x i32> @test1(<4 x float> %a, <4 x float> %b, <4 x i32> %c) {
; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0
; CHECK-NEXT: vandps %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ult <4 x float> %a, %b
%r = select <4 x i1> %f, <4 x i32> %c, <4 x i32> zeroinitializer
ret <4 x i32> %r
@@ -19,7 +18,6 @@ define <4 x i32> @test2(<4 x float> %a, <4 x float> %b, <4 x i32> %c) {
; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0
; CHECK-NEXT: vorps %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ult <4 x float> %a, %b
%r = select <4 x i1> %f, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> %c
ret <4 x i32> %r
@@ -31,7 +29,6 @@ define <4 x i32> @test3(<4 x float> %a, <4 x float> %b, <4 x i32> %c) {
; CHECK-NEXT: vcmpleps %xmm0, %xmm1, %xmm0
; CHECK-NEXT: vandps %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ult <4 x float> %a, %b
%r = select <4 x i1> %f, <4 x i32> zeroinitializer, <4 x i32> %c
ret <4 x i32> %r
@@ -43,7 +40,6 @@ define <4 x i32> @test4(<4 x float> %a, <4 x float> %b, <4 x i32> %c) {
; CHECK-NEXT: vcmpleps %xmm0, %xmm1, %xmm0
; CHECK-NEXT: vorps %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ult <4 x float> %a, %b
%r = select <4 x i1> %f, <4 x i32> %c, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>
ret <4 x i32> %r
@@ -54,7 +50,6 @@ define <4 x i32> @test5(<4 x float> %a, <4 x float> %b, <4 x i32> %c) {
; CHECK: # BB#0:
; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ult <4 x float> %a, %b
%r = sext <4 x i1> %f to <4 x i32>
ret <4 x i32> %r
@@ -65,7 +60,6 @@ define <4 x i32> @test6(<4 x float> %a, <4 x float> %b, <4 x i32> %c) {
; CHECK: # BB#0:
; CHECK-NEXT: vcmpleps %xmm0, %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%not.f = fcmp oge <4 x float> %a, %b
%r = sext <4 x i1> %not.f to <4 x i32>
ret <4 x i32> %r
@@ -77,7 +71,6 @@ define <4 x i32> @test7(<4 x float> %a, <4 x float> %b, <4 x i32>* %p) {
; CHECK-NEXT: vcmpnleps %xmm0, %xmm1, %xmm0
; CHECK-NEXT: vandps (%rdi), %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ult <4 x float> %a, %b
%l = load <4 x i32>, <4 x i32>* %p, align 16
%r = select <4 x i1> %f, <4 x i32> %l, <4 x i32> zeroinitializer
@@ -92,7 +85,6 @@ define <2 x double> @test1f(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK-NEXT: vcmpltpd %xmm0, %xmm1, %xmm0
; CHECK-NEXT: vandpd %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ogt <2 x double> %a, %b
%r = select <2 x i1> %f, <2 x double> %c, <2 x double> zeroinitializer
ret <2 x double> %r
@@ -104,7 +96,6 @@ define <2 x double> @test2f(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK-NEXT: vcmplepd %xmm0, %xmm1, %xmm0
; CHECK-NEXT: vorpd %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp oge <2 x double> %a, %b
%r = select <2 x i1> %f, <2 x double> <double 0xffffffffffffffff, double 0xffffffffffffffff>, <2 x double> %c
ret <2 x double> %r
@@ -116,7 +107,6 @@ define <2 x double> @test3f(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK-NEXT: vcmpnltpd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: vandpd %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp olt <2 x double> %a, %b
%r = select <2 x i1> %f, <2 x double> zeroinitializer, <2 x double> %c
ret <2 x double> %r
@@ -128,7 +118,6 @@ define <2 x double> @test4f(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK-NEXT: vcmpnlepd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: vorpd %xmm2, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ole <2 x double> %a, %b
%r = select <2 x i1> %f, <2 x double> %c, <2 x double> <double 0xffffffffffffffff, double 0xffffffffffffffff>
ret <2 x double> %r
@@ -139,7 +128,6 @@ define <2 x double> @test5f(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK: # BB#0:
; CHECK-NEXT: vcmpnlepd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ugt <2 x double> %a, %b
%r = select <2 x i1> %f, <2 x double> <double 0xffffffffffffffff, double 0xffffffffffffffff>, <2 x double> zeroinitializer
ret <2 x double> %r
@@ -150,7 +138,6 @@ define <2 x double> @test6f(<2 x double> %a, <2 x double> %b, <2 x double> %c) {
; CHECK: # BB#0:
; CHECK-NEXT: vcmpltpd %xmm0, %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp ule <2 x double> %a, %b
%r = select <2 x i1> %f, <2 x double> zeroinitializer, <2 x double> <double 0xffffffffffffffff, double 0xffffffffffffffff>
ret <2 x double> %r
@@ -162,7 +149,6 @@ define <2 x double> @test7f(<2 x double> %a, <2 x double> %b, <2 x double>* %p)
; CHECK-NEXT: vcmpeqpd %xmm1, %xmm0, %xmm0
; CHECK-NEXT: vandpd (%rdi), %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%f = fcmp oeq <2 x double> %a, %b
%l = load <2 x double>, <2 x double>* %p, align 16
%r = select <2 x i1> %f, <2 x double> %l, <2 x double> zeroinitializer
diff --git a/test/CodeGen/X86/sext-setcc-self.ll b/test/CodeGen/X86/sext-setcc-self.ll
index e739d21e64e0..9cbd3d85b381 100644
--- a/test/CodeGen/X86/sext-setcc-self.ll
+++ b/test/CodeGen/X86/sext-setcc-self.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-unknown-unknown < %s | FileCheck %s
define <4 x i32> @test_ueq(<4 x float> %in) {
@@ -6,7 +6,6 @@ define <4 x i32> @test_ueq(<4 x float> %in) {
; CHECK: # BB#0:
; CHECK-NEXT: pcmpeqd %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%t0 = fcmp ueq <4 x float> %in, %in
%t1 = sext <4 x i1> %t0 to <4 x i32>
ret <4 x i32> %t1
@@ -17,7 +16,6 @@ define <4 x i32> @test_uge(<4 x float> %in) {
; CHECK: # BB#0:
; CHECK-NEXT: pcmpeqd %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%t0 = fcmp uge <4 x float> %in, %in
%t1 = sext <4 x i1> %t0 to <4 x i32>
ret <4 x i32> %t1
@@ -28,7 +26,6 @@ define <4 x i32> @test_ule(<4 x float> %in) {
; CHECK: # BB#0:
; CHECK-NEXT: pcmpeqd %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%t0 = fcmp ule <4 x float> %in, %in
%t1 = sext <4 x i1> %t0 to <4 x i32>
ret <4 x i32> %t1
@@ -39,7 +36,6 @@ define <4 x i32> @test_one(<4 x float> %in) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%t0 = fcmp one <4 x float> %in, %in
%t1 = sext <4 x i1> %t0 to <4 x i32>
ret <4 x i32> %t1
@@ -50,7 +46,6 @@ define <4 x i32> @test_ogt(<4 x float> %in) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%t0 = fcmp ogt <4 x float> %in, %in
%t1 = sext <4 x i1> %t0 to <4 x i32>
ret <4 x i32> %t1
@@ -61,7 +56,6 @@ define <4 x i32> @test_olt(<4 x float> %in) {
; CHECK: # BB#0:
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
-;
%t0 = fcmp olt <4 x float> %in, %in
%t1 = sext <4 x i1> %t0 to <4 x i32>
ret <4 x i32> %t1
diff --git a/test/CodeGen/X86/shift-pcmp.ll b/test/CodeGen/X86/shift-pcmp.ll
index adfd2f143d17..f509da2674bc 100644
--- a/test/CodeGen/X86/shift-pcmp.ll
+++ b/test/CodeGen/X86/shift-pcmp.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -o - -mtriple=x86_64-unknown-unknown -mattr=+sse2 | FileCheck %s --check-prefix=SSE
; RUN: llc < %s -o - -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=AVX
@@ -14,7 +14,6 @@ define <8 x i16> @foo(<8 x i16> %a, <8 x i16> %b) {
; AVX-NEXT: vpcmpeqw %xmm1, %xmm0, %xmm0
; AVX-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0
; AVX-NEXT: retq
-;
%icmp = icmp eq <8 x i16> %a, %b
%zext = zext <8 x i1> %icmp to <8 x i16>
%shl = shl nuw nsw <8 x i16> %zext, <i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5>
@@ -34,7 +33,6 @@ define <8 x i16> @bar(<8 x i16> %a, <8 x i16> %b) {
; AVX-NEXT: vpcmpeqw %xmm1, %xmm0, %xmm0
; AVX-NEXT: vpand {{.*}}(%rip), %xmm0, %xmm0
; AVX-NEXT: retq
-;
%icmp = icmp eq <8 x i16> %a, %b
%zext = zext <8 x i1> %icmp to <8 x i16>
%shl = shl nuw nsw <8 x i16> %zext, <i16 5, i16 undef, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5>
diff --git a/test/CodeGen/X86/sincos-opt.ll b/test/CodeGen/X86/sincos-opt.ll
index f0dff3b806c5..e2fd63eab30f 100644
--- a/test/CodeGen/X86/sincos-opt.ll
+++ b/test/CodeGen/X86/sincos-opt.ll
@@ -1,10 +1,12 @@
; RUN: llc < %s -mtriple=x86_64-apple-macosx10.9.0 -mcpu=core2 | FileCheck %s --check-prefix=OSX_SINCOS
; RUN: llc < %s -mtriple=x86_64-apple-macosx10.8.0 -mcpu=core2 | FileCheck %s --check-prefix=OSX_NOOPT
-; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 | FileCheck %s --check-prefix=GNU_NOOPT
-; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNU_SINCOS
-; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNUX32_SINCOS
+; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 | FileCheck %s --check-prefix=GNU_SINCOS
+; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNU_SINCOS_FASTMATH
+; RUN: llc < %s -mtriple=x86_64-pc-linux-gnux32 -mcpu=core2 -enable-unsafe-fp-math | FileCheck %s --check-prefix=GNU_SINCOS_FASTMATH
-; Combine sin / cos into a single call.
+; Combine sin / cos into a single call unless they may write errno (as
+; captured by readnone attrbiute, controlled by clang -fmath-errno
+; setting).
; rdar://13087969
; rdar://13599493
@@ -15,25 +17,44 @@ entry:
; GNU_SINCOS: movss 4(%rsp), %xmm0
; GNU_SINCOS: addss (%rsp), %xmm0
-; GNUX32_SINCOS-LABEL: test1:
-; GNUX32_SINCOS: callq sincosf
-; GNUX32_SINCOS: movss 4(%esp), %xmm0
-; GNUX32_SINCOS: addss (%esp), %xmm0
-
-; GNU_NOOPT: test1
-; GNU_NOOPT: callq sinf
-; GNU_NOOPT: callq cosf
+; GNU_SINCOS_FASTMATH-LABEL: test1:
+; GNU_SINCOS_FASTMATH: callq sincosf
+; GNU_SINCOS_FASTMATH: movss 4(%{{[re]}}sp), %xmm0
+; GNU_SINCOS_FASTMATH: addss (%{{[re]}}sp), %xmm0
; OSX_SINCOS-LABEL: test1:
; OSX_SINCOS: callq ___sincosf_stret
; OSX_SINCOS: movshdup {{.*}} xmm1 = xmm0[1,1,3,3]
; OSX_SINCOS: addss %xmm1, %xmm0
-; OSX_NOOPT: test1
+; OSX_NOOPT-LABEL: test1:
; OSX_NOOPT: callq _sinf
; OSX_NOOPT: callq _cosf
- %call = tail call float @sinf(float %x) nounwind readnone
- %call1 = tail call float @cosf(float %x) nounwind readnone
+ %call = tail call float @sinf(float %x) readnone
+ %call1 = tail call float @cosf(float %x) readnone
+ %add = fadd float %call, %call1
+ ret float %add
+}
+
+define float @test1_errno(float %x) nounwind {
+entry:
+; GNU_SINCOS-LABEL: test1_errno:
+; GNU_SINCOS: callq sinf
+; GNU_SINCOS: callq cosf
+
+; GNU_SINCOS_FASTMATH-LABEL: test1_errno:
+; GNU_SINCOS_FASTMATH: callq sinf
+; GNU_SINCOS_FASTMATH: callq cosf
+
+; OSX_SINCOS-LABEL: test1_errno:
+; OSX_SINCOS: callq _sinf
+; OSX_SINCOS: callq _cosf
+
+; OSX_NOOPT-LABEL: test1_errno:
+; OSX_NOOPT: callq _sinf
+; OSX_NOOPT: callq _cosf
+ %call = tail call float @sinf(float %x)
+ %call1 = tail call float @cosf(float %x)
%add = fadd float %call, %call1
ret float %add
}
@@ -45,24 +66,43 @@ entry:
; GNU_SINCOS: movsd 16(%rsp), %xmm0
; GNU_SINCOS: addsd 8(%rsp), %xmm0
-; GNUX32_SINCOS-LABEL: test2:
-; GNUX32_SINCOS: callq sincos
-; GNUX32_SINCOS: movsd 16(%esp), %xmm0
-; GNUX32_SINCOS: addsd 8(%esp), %xmm0
-
-; GNU_NOOPT: test2:
-; GNU_NOOPT: callq sin
-; GNU_NOOPT: callq cos
+; GNU_SINCOS_FASTMATH-LABEL: test2:
+; GNU_SINCOS_FASTMATH: callq sincos
+; GNU_SINCOS_FASTMATH: movsd 16(%{{[re]}}sp), %xmm0
+; GNU_SINCOS_FASTMATH: addsd 8(%{{[re]}}sp), %xmm0
; OSX_SINCOS-LABEL: test2:
; OSX_SINCOS: callq ___sincos_stret
; OSX_SINCOS: addsd %xmm1, %xmm0
-; OSX_NOOPT: test2
+; OSX_NOOPT-LABEL: test2:
+; OSX_NOOPT: callq _sin
+; OSX_NOOPT: callq _cos
+ %call = tail call double @sin(double %x) readnone
+ %call1 = tail call double @cos(double %x) readnone
+ %add = fadd double %call, %call1
+ ret double %add
+}
+
+define double @test2_errno(double %x) nounwind {
+entry:
+; GNU_SINCOS-LABEL: test2_errno:
+; GNU_SINCOS: callq sin
+; GNU_SINCOS: callq cos
+
+; GNU_SINCOS_FASTMATH-LABEL: test2_errno:
+; GNU_SINCOS_FASTMATH: callq sin
+; GNU_SINCOS_FASTMATH: callq cos
+
+; OSX_SINCOS-LABEL: test2_errno:
+; OSX_SINCOS: callq _sin
+; OSX_SINCOS: callq _cos
+
+; OSX_NOOPT-LABEL: test2_errno:
; OSX_NOOPT: callq _sin
; OSX_NOOPT: callq _cos
- %call = tail call double @sin(double %x) nounwind readnone
- %call1 = tail call double @cos(double %x) nounwind readnone
+ %call = tail call double @sin(double %x)
+ %call1 = tail call double @cos(double %x)
%add = fadd double %call, %call1
ret double %add
}
@@ -70,29 +110,40 @@ entry:
define x86_fp80 @test3(x86_fp80 %x) nounwind {
entry:
; GNU_SINCOS-LABEL: test3:
+; GNU_SINCOS: callq sincosl
+; GNU_SINCOS: fldt 16(%rsp)
+; GNU_SINCOS: fldt 32(%rsp)
+; GNU_SINCOS: faddp %st(1)
+
+; GNU_SINCOS_FASTMATH-LABEL: test3:
+; GNU_SINCOS_FASTMATH: fsin
+; GNU_SINCOS_FASTMATH: fcos
+; GNU_SINCOS_FASTMATH: faddp %st(1)
+; GNU_SINCOS_FASTMATH: ret
+ %call = tail call x86_fp80 @sinl(x86_fp80 %x) readnone
+ %call1 = tail call x86_fp80 @cosl(x86_fp80 %x) readnone
+ %add = fadd x86_fp80 %call, %call1
+ ret x86_fp80 %add
+}
+
+define x86_fp80 @test3_errno(x86_fp80 %x) nounwind {
+entry:
+; GNU_SINCOS-LABEL: test3_errno:
; GNU_SINCOS: callq sinl
; GNU_SINCOS: callq cosl
-; GNU_SINCOS: ret
-; GNUX32_SINCOS-LABEL: test3:
-; GNUX32_SINCOS: callq sinl
-; GNUX32_SINCOS: callq cosl
-; GNUX32_SINCOS: ret
-
-; GNU_NOOPT: test3:
-; GNU_NOOPT: callq sinl
-; GNU_NOOPT: callq cosl
-
- %call = tail call x86_fp80 @sinl(x86_fp80 %x) nounwind
- %call1 = tail call x86_fp80 @cosl(x86_fp80 %x) nounwind
+; GNU_SINCOS_FASTMATH-LABEL: test3_errno:
+; GNU_SINCOS_FASTMATH: callq sinl
+; GNU_SINCOS_FASTMATH: callq cosl
+ %call = tail call x86_fp80 @sinl(x86_fp80 %x)
+ %call1 = tail call x86_fp80 @cosl(x86_fp80 %x)
%add = fadd x86_fp80 %call, %call1
ret x86_fp80 %add
}
-declare float @sinf(float) readonly
-declare double @sin(double) readonly
-declare float @cosf(float) readonly
-declare double @cos(double) readonly
-
+declare float @sinf(float)
+declare double @sin(double)
+declare float @cosf(float)
+declare double @cos(double)
declare x86_fp80 @sinl(x86_fp80)
declare x86_fp80 @cosl(x86_fp80)
diff --git a/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll b/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll
index 77497d38c897..2ecba887f7cb 100644
--- a/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll
+++ b/test/CodeGen/X86/sse-intrinsics-x86-upgrade.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=i686-apple-darwin -mattr=+sse2 | FileCheck %s
define void @test_x86_sse_storeu_ps(i8* %a0, <4 x float> %a1) {
diff --git a/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll b/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll
index 26af37e30295..9bda90a23023 100644
--- a/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll
+++ b/test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=i386-apple-darwin -mattr=+sse4.1 | FileCheck %s
; This test works just like the non-upgrade one except that it only checks
@@ -230,7 +230,6 @@ define <16 x i8> @max_epi8(<16 x i8> %a0, <16 x i8> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pmaxsb %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <16 x i8> @llvm.x86.sse41.pmaxsb(<16 x i8> %a0, <16 x i8> %a1)
ret <16 x i8> %res
}
@@ -241,7 +240,6 @@ define <16 x i8> @min_epi8(<16 x i8> %a0, <16 x i8> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pminsb %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <16 x i8> @llvm.x86.sse41.pminsb(<16 x i8> %a0, <16 x i8> %a1)
ret <16 x i8> %res
}
@@ -252,7 +250,6 @@ define <8 x i16> @max_epu16(<8 x i16> %a0, <8 x i16> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pmaxuw %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <8 x i16> @llvm.x86.sse41.pmaxuw(<8 x i16> %a0, <8 x i16> %a1)
ret <8 x i16> %res
}
@@ -263,7 +260,6 @@ define <8 x i16> @min_epu16(<8 x i16> %a0, <8 x i16> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pminuw %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <8 x i16> @llvm.x86.sse41.pminuw(<8 x i16> %a0, <8 x i16> %a1)
ret <8 x i16> %res
}
@@ -274,7 +270,6 @@ define <4 x i32> @max_epi32(<4 x i32> %a0, <4 x i32> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pmaxsd %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <4 x i32> @llvm.x86.sse41.pmaxsd(<4 x i32> %a0, <4 x i32> %a1)
ret <4 x i32> %res
}
@@ -285,7 +280,6 @@ define <4 x i32> @min_epi32(<4 x i32> %a0, <4 x i32> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pminsd %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <4 x i32> @llvm.x86.sse41.pminsd(<4 x i32> %a0, <4 x i32> %a1)
ret <4 x i32> %res
}
@@ -296,7 +290,6 @@ define <4 x i32> @max_epu32(<4 x i32> %a0, <4 x i32> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pmaxud %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <4 x i32> @llvm.x86.sse41.pmaxud(<4 x i32> %a0, <4 x i32> %a1)
ret <4 x i32> %res
}
@@ -307,7 +300,6 @@ define <4 x i32> @min_epu32(<4 x i32> %a0, <4 x i32> %a1) {
; CHECK: ## BB#0:
; CHECK-NEXT: pminud %xmm1, %xmm0
; CHECK-NEXT: retl
-;
%res = call <4 x i32> @llvm.x86.sse41.pminud(<4 x i32> %a0, <4 x i32> %a1)
ret <4 x i32> %res
}
diff --git a/test/CodeGen/X86/stack-folding-int-avx512.ll b/test/CodeGen/X86/stack-folding-int-avx512.ll
index 38e19efb7132..362e656b4f22 100644
--- a/test/CodeGen/X86/stack-folding-int-avx512.ll
+++ b/test/CodeGen/X86/stack-folding-int-avx512.ll
@@ -1,4 +1,4 @@
-; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512bw,+avx512dq,+avx512vbmi < %s | FileCheck %s
+; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512f,+avx512bw,+avx512dq,+avx512vbmi,+avx512cd < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-unknown"
@@ -450,6 +450,24 @@ define <64 x i8> @stack_fold_palignr_maskz(<64 x i8> %a0, <64 x i8> %a1, i64 %ma
ret <64 x i8> %4
}
+define <16 x i32> @stack_fold_vpconflictd(<16 x i32> %a0) {
+ ;CHECK-LABEL: stack_fold_vpconflictd
+ ;CHECK: vpconflictd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <16 x i32> @llvm.x86.avx512.mask.conflict.d.512(<16 x i32> %a0, <16 x i32> undef, i16 -1)
+ ret <16 x i32> %2
+}
+declare <16 x i32> @llvm.x86.avx512.mask.conflict.d.512(<16 x i32>, <16 x i32>, i16) nounwind readonly
+
+define <8 x i64> @stack_fold_vpconflictq(<8 x i64> %a0) {
+ ;CHECK-LABEL: stack_fold_vpconflictq
+ ;CHECK: vpconflictq {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <8 x i64> @llvm.x86.avx512.mask.conflict.q.512(<8 x i64> %a0, <8 x i64> undef, i8 -1)
+ ret <8 x i64> %2
+}
+declare <8 x i64> @llvm.x86.avx512.mask.conflict.q.512(<8 x i64>, <8 x i64>, i8) nounwind readnone
+
define i64 @stack_fold_pcmpeqb(<64 x i8> %a0, <64 x i8> %a1) {
;CHECK-LABEL: stack_fold_pcmpeqb
;CHECK: vpcmpeqb {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{.*#+}} 64-byte Folded Reload
@@ -486,6 +504,61 @@ define i32 @stack_fold_pcmpeqw(<32 x i16> %a0, <32 x i16> %a1) {
ret i32 %3
}
+define i16 @stack_fold_pcmpeqd_mask(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) {
+ ;CHECK-LABEL: stack_fold_pcmpeqd_mask
+ ;CHECK: vpcmpeqd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{{%k[0-7]}}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ ; load and add are here to keep the operations below the side effecting block and to avoid folding the wrong load
+ %2 = load <16 x i32>, <16 x i32>* %a2
+ %3 = add <16 x i32> %a1, %2
+ %4 = bitcast i16 %mask to <16 x i1>
+ %5 = icmp eq <16 x i32> %3, %a0
+ %6 = and <16 x i1> %4, %5
+ %7 = bitcast <16 x i1> %6 to i16
+ ret i16 %7
+}
+
+define i16 @stack_fold_pcmpeqd_mask_commuted(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) {
+ ;CHECK-LABEL: stack_fold_pcmpeqd_mask_commuted
+ ;CHECK: vpcmpeqd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{{%k[0-7]}}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ ; load and add are here to keep the operations below the side effecting block and to avoid folding the wrong load
+ %2 = load <16 x i32>, <16 x i32>* %a2
+ %3 = add <16 x i32> %a1, %2
+ %4 = bitcast i16 %mask to <16 x i1>
+ %5 = icmp eq <16 x i32> %a0, %3
+ %6 = and <16 x i1> %4, %5
+ %7 = bitcast <16 x i1> %6 to i16
+ ret i16 %7
+}
+
+define i16 @stack_fold_pcmpled_mask(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) {
+ ;CHECK-LABEL: stack_fold_pcmpled_mask
+ ;CHECK: vpcmpled {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{{%k[0-7]}}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ ; load and add are here to keep the operations below the side effecting block and to avoid folding the wrong load
+ %2 = load <16 x i32>, <16 x i32>* %a2
+ %3 = add <16 x i32> %a1, %2
+ %4 = bitcast i16 %mask to <16 x i1>
+ %5 = icmp sge <16 x i32> %a0, %3
+ %6 = and <16 x i1> %4, %5
+ %7 = bitcast <16 x i1> %6 to i16
+ ret i16 %7
+}
+
+define i16 @stack_fold_pcmpleud(<16 x i32> %a0, <16 x i32> %a1, <16 x i32>* %a2, i16 %mask) {
+ ;CHECK-LABEL: stack_fold_pcmpleud
+ ;CHECK: vpcmpleud {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%k[0-7]}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = load <16 x i32>, <16 x i32>* %a2
+ %3 = add <16 x i32> %a1, %2
+ %4 = bitcast i16 %mask to <16 x i1>
+ %5 = icmp uge <16 x i32> %a0, %3
+ %6 = and <16 x i1> %5, %4
+ %7 = bitcast <16 x i1> %6 to i16
+ ret i16 %7
+}
+
define <64 x i8> @stack_fold_permbvar(<64 x i8> %a0, <64 x i8> %a1) {
;CHECK-LABEL: stack_fold_permbvar
;CHECK: vpermb {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload
@@ -740,6 +813,24 @@ define <8 x i16> @stack_fold_pinsrw(<8 x i16> %a0, i16 %a1) {
ret <8 x i16> %2
}
+define <16 x i32> @stack_fold_vplzcntd(<16 x i32> %a0) {
+ ;CHECK-LABEL: stack_fold_vplzcntd
+ ;CHECK: vplzcntd {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <16 x i32> @llvm.ctlz.v16i32(<16 x i32> %a0)
+ ret <16 x i32> %2
+}
+declare <16 x i32> @llvm.ctlz.v16i32(<16 x i32>) nounwind readonly
+
+define <8 x i64> @stack_fold_vplzcntq(<8 x i64> %a0) {
+ ;CHECK-LABEL: stack_fold_vplzcntq
+ ;CHECK: vplzcntq {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <8 x i64> @llvm.ctlz.v8i64(<8 x i64> %a0)
+ ret <8 x i64> %2
+}
+declare <8 x i64> @llvm.ctlz.v8i64(<8 x i64>) nounwind readnone
+
define <32 x i16> @stack_fold_pmaddubsw_zmm(<64 x i8> %a0, <64 x i8> %a1) {
;CHECK-LABEL: stack_fold_pmaddubsw_zmm
;CHECK: vpmaddubsw {{-?[0-9]*}}(%rsp), {{%zmm[0-9][0-9]*}}, {{%zmm[0-9][0-9]*}} {{.*#+}} 64-byte Folded Reload
diff --git a/test/CodeGen/X86/stack-folding-int-avx512vl.ll b/test/CodeGen/X86/stack-folding-int-avx512vl.ll
index 7ce798f778a3..26e97ea4e599 100644
--- a/test/CodeGen/X86/stack-folding-int-avx512vl.ll
+++ b/test/CodeGen/X86/stack-folding-int-avx512vl.ll
@@ -1,4 +1,4 @@
-; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512vl,+avx512bw,+avx512dq,+avx512vbmi < %s | FileCheck %s
+; RUN: llc -O3 -disable-peephole -mtriple=x86_64-unknown-unknown -mattr=+avx512vl,+avx512bw,+avx512dq,+avx512vbmi,+avx512cd < %s | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-unknown"
@@ -81,6 +81,42 @@ define <16 x i16> @stack_fold_pavgw_ymm(<16 x i16> %a0, <16 x i16> %a1) {
}
declare <16 x i16> @llvm.x86.avx2.pavg.w(<16 x i16>, <16 x i16>) nounwind readnone
+define <4 x i32> @stack_fold_vpconflictd(<4 x i32> %a0) {
+ ;CHECK-LABEL: stack_fold_vpconflictd
+ ;CHECK: vpconflictd {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <4 x i32> @llvm.x86.avx512.mask.conflict.d.128(<4 x i32> %a0, <4 x i32> undef, i8 -1)
+ ret <4 x i32> %2
+}
+declare <4 x i32> @llvm.x86.avx512.mask.conflict.d.128(<4 x i32>, <4 x i32>, i8) nounwind readonly
+
+define <8 x i32> @stack_fold_vpconflictd_ymm(<8 x i32> %a0) {
+ ;CHECK-LABEL: stack_fold_vpconflictd_ymm
+ ;CHECK: vpconflictd {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <8 x i32> @llvm.x86.avx512.mask.conflict.d.256(<8 x i32> %a0, <8 x i32> undef, i8 -1)
+ ret <8 x i32> %2
+}
+declare <8 x i32> @llvm.x86.avx512.mask.conflict.d.256(<8 x i32>, <8 x i32>, i8) nounwind readonly
+
+define <2 x i64> @stack_fold_vpconflictq(<2 x i64> %a0) {
+ ;CHECK-LABEL: stack_fold_vpconflictq
+ ;CHECK: vpconflictq {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <2 x i64> @llvm.x86.avx512.mask.conflict.q.128(<2 x i64> %a0, <2 x i64> undef, i8 -1)
+ ret <2 x i64> %2
+}
+declare <2 x i64> @llvm.x86.avx512.mask.conflict.q.128(<2 x i64>, <2 x i64>, i8) nounwind readnone
+
+define <4 x i64> @stack_fold_vpconflictq_ymm(<4 x i64> %a0) {
+ ;CHECK-LABEL: stack_fold_vpconflictq_ymm
+ ;CHECK: vpconflictq {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <4 x i64> @llvm.x86.avx512.mask.conflict.q.256(<4 x i64> %a0, <4 x i64> undef, i8 -1)
+ ret <4 x i64> %2
+}
+declare <4 x i64> @llvm.x86.avx512.mask.conflict.q.256(<4 x i64>, <4 x i64>, i8) nounwind readnone
+
define <4 x i32> @stack_fold_extracti32x4(<8 x i32> %a0, <8 x i32> %a1) {
;CHECK-LABEL: stack_fold_extracti32x4
;CHECK: vextracti128 $1, {{%ymm[0-9][0-9]*}}, {{-?[0-9]*}}(%rsp) {{.*#+}} 16-byte Folded Spill
@@ -708,6 +744,42 @@ define <16 x i16> @stack_fold_permwvar(<16 x i16> %a0, <16 x i16> %a1) {
}
declare <16 x i16> @llvm.x86.avx512.mask.permvar.hi.256(<16 x i16>, <16 x i16>, <16 x i16>, i16) nounwind readonly
+define <4 x i32> @stack_fold_vplzcntd(<4 x i32> %a0) {
+ ;CHECK-LABEL: stack_fold_vplzcntd
+ ;CHECK: vplzcntd {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a0)
+ ret <4 x i32> %2
+}
+declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>) nounwind readonly
+
+define <8 x i32> @stack_fold_vplzcntd_ymm(<8 x i32> %a0) {
+ ;CHECK-LABEL: stack_fold_vplzcntd_ymm
+ ;CHECK: vplzcntd {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <8 x i32> @llvm.ctlz.v8i32(<8 x i32> %a0)
+ ret <8 x i32> %2
+}
+declare <8 x i32> @llvm.ctlz.v8i32(<8 x i32>) nounwind readonly
+
+define <2 x i64> @stack_fold_vplzcntq(<2 x i64> %a0) {
+ ;CHECK-LABEL: stack_fold_vplzcntq
+ ;CHECK: vplzcntq {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %a0)
+ ret <2 x i64> %2
+}
+declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>) nounwind readnone
+
+define <4 x i64> @stack_fold_vplzcntq_ymm(<4 x i64> %a0) {
+ ;CHECK-LABEL: stack_fold_vplzcntq_ymm
+ ;CHECK: vplzcntq {{-?[0-9]*}}(%rsp), {{%ymm[0-9][0-9]*}} {{.*#+}} 32-byte Folded Reload
+ %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{xmm16},~{xmm17},~{xmm18},~{xmm19},~{xmm20},~{xmm21},~{xmm22},~{xmm23},~{xmm24},~{xmm25},~{xmm26},~{xmm27},~{xmm28},~{xmm29},~{xmm30},~{xmm31},~{flags}"()
+ %2 = call <4 x i64> @llvm.ctlz.v4i64(<4 x i64> %a0)
+ ret <4 x i64> %2
+}
+declare <4 x i64> @llvm.ctlz.v4i64(<4 x i64>) nounwind readnone
+
define <8 x i16> @stack_fold_pmaddubsw(<16 x i8> %a0, <16 x i8> %a1) {
;CHECK-LABEL: stack_fold_pmaddubsw
;CHECK: vpmaddubsw {{-?[0-9]*}}(%rsp), {{%xmm[0-9][0-9]*}}, {{%xmm[0-9][0-9]*}} {{.*#+}} 16-byte Folded Reload
diff --git a/test/CodeGen/X86/statepoint-live-in.ll b/test/CodeGen/X86/statepoint-live-in.ll
index aaa4d7c8422a..0179d37ad4e1 100644
--- a/test/CodeGen/X86/statepoint-live-in.ll
+++ b/test/CodeGen/X86/statepoint-live-in.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs -O3 < %s | FileCheck %s
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.11.0"
@@ -16,7 +16,6 @@ define void @test1(i32 %a) gc "statepoint-example" {
; CHECK-NEXT: Ltmp0:
; CHECK-NEXT: popq %rax
; CHECK-NEXT: retq
-;
entry:
; We expect the argument to be passed in an extra register to bar
%statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a)
@@ -49,7 +48,6 @@ define void @test2(i32 %a, i32 %b) gc "statepoint-example" {
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: popq %rbp
; CHECK-NEXT: retq
-;
entry:
; Because the first call clobbers esi, we have to move the values into
; new registers. Note that they stay in the registers for both calls.
@@ -68,7 +66,6 @@ define void @test3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %
; CHECK-NEXT: Ltmp3:
; CHECK-NEXT: popq %rax
; CHECK-NEXT: retq
-;
entry:
; We directly reference the argument slot
%statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 9, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i)
@@ -89,7 +86,6 @@ define void @test4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %
; CHECK-NEXT: Ltmp4:
; CHECK-NEXT: popq %rax
; CHECK-NEXT: retq
-;
entry:
%statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 26, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z)
ret void
@@ -111,7 +107,6 @@ define i32 addrspace(1)* @test5(i32 %a, i32 addrspace(1)* %p) gc "statepoint-ex
; CHECK-NEXT: movq (%rsp), %rax
; CHECK-NEXT: popq %rcx
; CHECK-NEXT: retq
-;
entry:
%token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a, i32 addrspace(1)* %p, i32 addrspace(1)* %p)
%p2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token, i32 9, i32 9)
@@ -139,7 +134,6 @@ define void @test6(i32 %a) gc "statepoint-example" {
; CHECK-NEXT: addq $16, %rsp
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: retq
-;
entry:
call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 1, i32 %a)
call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 1, i32 %a)
diff --git a/test/CodeGen/X86/swifterror.ll b/test/CodeGen/X86/swifterror.ll
index 5704d1919988..1ecd33743d21 100644
--- a/test/CodeGen/X86/swifterror.ll
+++ b/test/CodeGen/X86/swifterror.ll
@@ -712,3 +712,111 @@ trueBB:
falseBB:
ret void
}
+
+
+declare swiftcc void @foo2(%swift_error** swifterror)
+
+; Make sure we properly assign registers during fast-isel.
+; CHECK-O0-LABEL: testAssign
+; CHECK-O0: pushq %r12
+; CHECK-O0: xorl [[ZERO:%[a-z0-9]+]], [[ZERO]]
+; CHECK-O0: movl [[ZERO]], %r12d
+; CHECK-O0: callq _foo2
+; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
+;
+; CHECK-O0: movq [[SLOT]], %rax
+; CHECK-O0: popq %r12
+; CHECK-O0: retq
+
+; CHECK-APPLE-LABEL: testAssign
+; CHECK-APPLE: pushq %r12
+; CHECK-APPLE: xorl %r12d, %r12d
+; CHECK-APPLE: callq _foo2
+; CHECK-APPLE: movq %r12, %rax
+; CHECK-APPLE: popq %r12
+; CHECK-APPLE: retq
+
+define swiftcc %swift_error* @testAssign(i8* %error_ref) {
+entry:
+ %error_ptr = alloca swifterror %swift_error*
+ store %swift_error* null, %swift_error** %error_ptr
+ call swiftcc void @foo2(%swift_error** swifterror %error_ptr)
+ br label %a
+
+a:
+ %error = load %swift_error*, %swift_error** %error_ptr
+ ret %swift_error* %error
+}
+
+; CHECK-O0-LABEL: testAssign2
+; CHECK-O0: movq %r12, {{.*}}
+; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
+; CHECK-O0: jmp
+; CHECK-O0: movq [[SLOT]], %rax
+; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
+; CHECK-O0: movq [[SLOT2]], %r12
+; CHECK-O0: retq
+
+; CHECK-APPLE-LABEL: testAssign2
+; CHECK-APPLE: movq %r12, %rax
+; CHECK-APPLE: retq
+define swiftcc %swift_error* @testAssign2(i8* %error_ref, %swift_error** swifterror %err) {
+entry:
+ br label %a
+
+a:
+ %error = load %swift_error*, %swift_error** %err
+ ret %swift_error* %error
+}
+
+; CHECK-O0-LABEL: testAssign3
+; CHECK-O0: callq _foo2
+; CHECK-O0: movq %r12, [[SLOT:[-a-z0-9\(\)\%]*]]
+; CHECK-O0: movq [[SLOT]], %rax
+; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
+; CHECK-O0: movq [[SLOT2]], %r12
+; CHECK-O0: addq $24, %rsp
+; CHECK-O0: retq
+
+; CHECK-APPLE-LABEL: testAssign3
+; CHECK-APPLE: callq _foo2
+; CHECK-APPLE: movq %r12, %rax
+; CHECK-APPLE: retq
+
+define swiftcc %swift_error* @testAssign3(i8* %error_ref, %swift_error** swifterror %err) {
+entry:
+ call swiftcc void @foo2(%swift_error** swifterror %err)
+ br label %a
+
+a:
+ %error = load %swift_error*, %swift_error** %err
+ ret %swift_error* %error
+}
+
+
+; CHECK-O0-LABEL: testAssign4
+; CHECK-O0: callq _foo2
+; CHECK-O0: xorl %ecx, %ecx
+; CHECK-O0: movl %ecx, %eax
+; CHECK-O0: movq %rax, [[SLOT:[-a-z0-9\(\)\%]*]]
+; CHECK-O0: movq [[SLOT]], %rax
+; CHECK-O0: movq %rax, [[SLOT2:[-a-z0-9\(\)\%]*]]
+; CHECK-O0: movq [[SLOT2]], %r12
+; CHECK-O0: retq
+
+; CHECK-APPLE-LABEL: testAssign4
+; CHECK-APPLE: callq _foo2
+; CHECK-APPLE: xorl %eax, %eax
+; CHECK-APPLE: xorl %r12d, %r12d
+; CHECK-APPLE: retq
+
+define swiftcc %swift_error* @testAssign4(i8* %error_ref, %swift_error** swifterror %err) {
+entry:
+ call swiftcc void @foo2(%swift_error** swifterror %err)
+ store %swift_error* null, %swift_error** %err
+ br label %a
+
+a:
+ %error = load %swift_error*, %swift_error** %err
+ ret %swift_error* %error
+}
diff --git a/test/CodeGen/X86/urem-i8-constant.ll b/test/CodeGen/X86/urem-i8-constant.ll
index 45717f985c23..2a659b20de8f 100644
--- a/test/CodeGen/X86/urem-i8-constant.ll
+++ b/test/CodeGen/X86/urem-i8-constant.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=i386-unknown-unknown | FileCheck %s
define i8 @foo(i8 %tmp325) {
@@ -14,7 +14,6 @@ define i8 @foo(i8 %tmp325) {
; CHECK-NEXT: subb %al, %cl
; CHECK-NEXT: movl %ecx, %eax
; CHECK-NEXT: retl
-;
%t546 = urem i8 %tmp325, 37
ret i8 %t546
}
diff --git a/test/CodeGen/X86/urem-power-of-two.ll b/test/CodeGen/X86/urem-power-of-two.ll
index 469c573443ea..1b56c87aad5f 100644
--- a/test/CodeGen/X86/urem-power-of-two.ll
+++ b/test/CodeGen/X86/urem-power-of-two.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
; The easy case: a constant power-of-2 divisor.
@@ -9,7 +9,6 @@ define i64 @const_pow_2(i64 %x) {
; CHECK-NEXT: andl $31, %edi
; CHECK-NEXT: movq %rdi, %rax
; CHECK-NEXT: retq
-;
%urem = urem i64 %x, 32
ret i64 %urem
}
@@ -25,7 +24,6 @@ define i25 @shift_left_pow_2(i25 %x, i25 %y) {
; CHECK-NEXT: addl $33554431, %eax # imm = 0x1FFFFFF
; CHECK-NEXT: andl %edi, %eax
; CHECK-NEXT: retq
-;
%shl = shl i25 1, %y
%urem = urem i25 %x, %shl
ret i25 %urem
@@ -43,7 +41,6 @@ define i16 @shift_right_pow_2(i16 %x, i16 %y) {
; CHECK-NEXT: andl %edi, %eax
; CHECK-NEXT: # kill: %AX<def> %AX<kill> %EAX<kill>
; CHECK-NEXT: retq
-;
%shr = lshr i16 -32768, %y
%urem = urem i16 %x, %shr
ret i16 %urem
@@ -61,7 +58,6 @@ define i8 @and_pow_2(i8 %x, i8 %y) {
; CHECK-NEXT: movzbl %ah, %eax # NOREX
; CHECK-NEXT: # kill: %AL<def> %AL<kill> %EAX<kill>
; CHECK-NEXT: retq
-;
%and = and i8 %y, 4
%urem = urem i8 %x, %and
ret i8 %urem
@@ -74,7 +70,6 @@ define <4 x i32> @vec_const_pow_2(<4 x i32> %x) {
; CHECK: # BB#0:
; CHECK-NEXT: andps {{.*}}(%rip), %xmm0
; CHECK-NEXT: retq
-;
%urem = urem <4 x i32> %x, <i32 16, i32 16, i32 16, i32 16>
ret <4 x i32> %urem
}
diff --git a/test/CodeGen/X86/vec3.ll b/test/CodeGen/X86/vec3.ll
index 8eaf9f4f48e4..e9c47ffd21c6 100644
--- a/test/CodeGen/X86/vec3.ll
+++ b/test/CodeGen/X86/vec3.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=sse | FileCheck %s
define <3 x float> @fadd(<3 x float> %v, float %d) {
@@ -7,7 +7,6 @@ define <3 x float> @fadd(<3 x float> %v, float %d) {
; CHECK-NEXT: shufps {{.*#+}} xmm1 = xmm1[0,0,0,3]
; CHECK-NEXT: addps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%ins = insertelement <3 x float> undef, float %d, i32 0
%splat = shufflevector <3 x float> %ins, <3 x float> undef, <3 x i32> zeroinitializer
%add = fadd <3 x float> %splat, %v
@@ -23,7 +22,6 @@ define <3 x float> @fdiv(<3 x float> %v, float %d) {
; CHECK-NEXT: divps %xmm0, %xmm1
; CHECK-NEXT: movaps %xmm1, %xmm0
; CHECK-NEXT: retq
-;
%ins = insertelement <3 x float> undef, float %d, i32 0
%splat = shufflevector <3 x float> %ins, <3 x float> undef, <3 x i32> zeroinitializer
%div = fdiv <3 x float> %splat, %v
diff --git a/test/CodeGen/X86/vector-compare-combines.ll b/test/CodeGen/X86/vector-compare-combines.ll
index c25474d92f9c..bd7cbfb4bac0 100644
--- a/test/CodeGen/X86/vector-compare-combines.ll
+++ b/test/CodeGen/X86/vector-compare-combines.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.2 | FileCheck %s --check-prefix=SSE --check-prefix=SSE42
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s --check-prefix=AVX --check-prefix=AVX1
@@ -17,7 +17,6 @@ define <4 x i32> @PR27924_cmpeq(<4 x i32> %a, <4 x i32> %b) {
; AVX: # BB#0:
; AVX-NEXT: vpcmpeqd %xmm0, %xmm0, %xmm0
; AVX-NEXT: retq
-;
%cmp = icmp sgt <4 x i32> %a, %b
%max = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> %b
%sse_max = tail call <4 x i32> @llvm.x86.sse41.pmaxsd(<4 x i32> %a, <4 x i32> %b)
@@ -36,7 +35,6 @@ define <4 x i32> @PR27924_cmpgt(<4 x i32> %a, <4 x i32> %b) {
; AVX: # BB#0:
; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0
; AVX-NEXT: retq
-;
%cmp = icmp sgt <4 x i32> %a, %b
%max = select <4 x i1> %cmp, <4 x i32> %a, <4 x i32> %b
%sse_max = tail call <4 x i32> @llvm.x86.sse41.pmaxsd(<4 x i32> %a, <4 x i32> %b)
diff --git a/test/CodeGen/X86/vector-shuffle-256-v16.ll b/test/CodeGen/X86/vector-shuffle-256-v16.ll
index fad5586dd77c..d34728df29b7 100644
--- a/test/CodeGen/X86/vector-shuffle-256-v16.ll
+++ b/test/CodeGen/X86/vector-shuffle-256-v16.ll
@@ -1559,6 +1559,24 @@ define <16 x i16> @shuffle_v16i16_17_18_19_20_21_22_23_zz_25_26_27_28_29_30_31_z
ret <16 x i16> %shuffle
}
+define <16 x i16> @shuffle_v16i16_06_07_01_02_07_00_04_05_14_15_09_10_15_08_12_13(<16 x i16> %a) {
+; AVX1-LABEL: shuffle_v16i16_06_07_01_02_07_00_04_05_14_15_09_10_15_08_12_13:
+; AVX1: # BB#0:
+; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm1
+; AVX1-NEXT: vmovdqa {{.*#+}} xmm2 = [12,13,14,15,2,3,4,5,14,15,0,1,8,9,10,11]
+; AVX1-NEXT: vpshufb %xmm2, %xmm1, %xmm1
+; AVX1-NEXT: vpshufb %xmm2, %xmm0, %xmm0
+; AVX1-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
+; AVX1-NEXT: retq
+;
+; AVX2OR512VL-LABEL: shuffle_v16i16_06_07_01_02_07_00_04_05_14_15_09_10_15_08_12_13:
+; AVX2OR512VL: # BB#0:
+; AVX2OR512VL-NEXT: vpshufb {{.*#+}} ymm0 = ymm0[12,13,14,15,2,3,4,5,14,15,0,1,8,9,10,11,28,29,30,31,18,19,20,21,30,31,16,17,24,25,26,27]
+; AVX2OR512VL-NEXT: retq
+ %1 = shufflevector <16 x i16> %a, <16 x i16> undef, <16 x i32> <i32 6, i32 7, i32 1, i32 2, i32 7, i32 0, i32 4, i32 5, i32 14, i32 15, i32 9, i32 10, i32 15, i32 8, i32 12, i32 13>
+ ret <16 x i16> %1
+}
+
;
; Shuffle to logical bit shifts
;
diff --git a/test/CodeGen/X86/vzero-excess.ll b/test/CodeGen/X86/vzero-excess.ll
index 0ed90741b61e..9ddafec65182 100644
--- a/test/CodeGen/X86/vzero-excess.ll
+++ b/test/CodeGen/X86/vzero-excess.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s
; In the following 4 tests, the existing call to VZU/VZA ensures clean state before
diff --git a/test/CodeGen/X86/x86-interleaved-access.ll b/test/CodeGen/X86/x86-interleaved-access.ll
index 74214aa1b8b7..ec8bce1b43cc 100644
--- a/test/CodeGen/X86/x86-interleaved-access.ll
+++ b/test/CodeGen/X86/x86-interleaved-access.ll
@@ -9,8 +9,8 @@ define <4 x double> @load_factorf64_4(<16 x double>* %ptr) {
; AVX-NEXT: vmovupd 32(%rdi), %ymm1
; AVX-NEXT: vmovupd 64(%rdi), %ymm2
; AVX-NEXT: vmovupd 96(%rdi), %ymm3
-; AVX-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm4
-; AVX-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm5
+; AVX-NEXT: vperm2f128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1]
+; AVX-NEXT: vperm2f128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1]
; AVX-NEXT: vhaddpd %ymm5, %ymm4, %ymm4
; AVX-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3]
; AVX-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3]
@@ -37,8 +37,8 @@ define <4 x double> @load_factorf64_2(<16 x double>* %ptr) {
; AVX-NEXT: vmovupd 32(%rdi), %ymm1
; AVX-NEXT: vmovupd 64(%rdi), %ymm2
; AVX-NEXT: vmovupd 96(%rdi), %ymm3
-; AVX-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm4
-; AVX-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm5
+; AVX-NEXT: vperm2f128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1]
+; AVX-NEXT: vperm2f128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1]
; AVX-NEXT: vunpcklpd {{.*#+}} ymm4 = ymm4[0],ymm5[0],ymm4[2],ymm5[2]
; AVX-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3]
; AVX-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3]
@@ -53,25 +53,15 @@ define <4 x double> @load_factorf64_2(<16 x double>* %ptr) {
}
define <4 x double> @load_factorf64_1(<16 x double>* %ptr) {
-; AVX1-LABEL: load_factorf64_1:
-; AVX1: # BB#0:
-; AVX1-NEXT: vmovups (%rdi), %ymm0
-; AVX1-NEXT: vmovups 32(%rdi), %ymm1
-; AVX1-NEXT: vinsertf128 $1, 64(%rdi), %ymm0, %ymm0
-; AVX1-NEXT: vinsertf128 $1, 96(%rdi), %ymm1, %ymm1
-; AVX1-NEXT: vunpcklpd {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[2],ymm1[2]
-; AVX1-NEXT: vmulpd %ymm0, %ymm0, %ymm0
-; AVX1-NEXT: retq
-;
-; AVX2-LABEL: load_factorf64_1:
-; AVX2: # BB#0:
-; AVX2-NEXT: vmovupd (%rdi), %ymm0
-; AVX2-NEXT: vmovupd 32(%rdi), %ymm1
-; AVX2-NEXT: vinsertf128 $1, 64(%rdi), %ymm0, %ymm0
-; AVX2-NEXT: vinsertf128 $1, 96(%rdi), %ymm1, %ymm1
-; AVX2-NEXT: vunpcklpd {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[2],ymm1[2]
-; AVX2-NEXT: vmulpd %ymm0, %ymm0, %ymm0
-; AVX2-NEXT: retq
+; AVX-LABEL: load_factorf64_1:
+; AVX: # BB#0:
+; AVX-NEXT: vmovupd (%rdi), %ymm0
+; AVX-NEXT: vmovupd 32(%rdi), %ymm1
+; AVX-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[0,1],mem[0,1]
+; AVX-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[0,1],mem[0,1]
+; AVX-NEXT: vunpcklpd {{.*#+}} ymm0 = ymm0[0],ymm1[0],ymm0[2],ymm1[2]
+; AVX-NEXT: vmulpd %ymm0, %ymm0, %ymm0
+; AVX-NEXT: retq
%wide.vec = load <16 x double>, <16 x double>* %ptr, align 16
%strided.v0 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
%strided.v3 = shufflevector <16 x double> %wide.vec, <16 x double> undef, <4 x i32> <i32 0, i32 4, i32 8, i32 12>
@@ -86,8 +76,8 @@ define <4 x i64> @load_factori64_4(<16 x i64>* %ptr) {
; AVX1-NEXT: vmovupd 32(%rdi), %ymm1
; AVX1-NEXT: vmovupd 64(%rdi), %ymm2
; AVX1-NEXT: vmovupd 96(%rdi), %ymm3
-; AVX1-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm4
-; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm5
+; AVX1-NEXT: vperm2f128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1]
+; AVX1-NEXT: vperm2f128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1]
; AVX1-NEXT: vperm2f128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3]
; AVX1-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3]
; AVX1-NEXT: vunpcklpd {{.*#+}} ymm2 = ymm4[0],ymm5[0],ymm4[2],ymm5[2]
@@ -113,8 +103,8 @@ define <4 x i64> @load_factori64_4(<16 x i64>* %ptr) {
; AVX2-NEXT: vmovdqu 32(%rdi), %ymm1
; AVX2-NEXT: vmovdqu 64(%rdi), %ymm2
; AVX2-NEXT: vmovdqu 96(%rdi), %ymm3
-; AVX2-NEXT: vinserti128 $1, %xmm2, %ymm0, %ymm4
-; AVX2-NEXT: vinserti128 $1, %xmm3, %ymm1, %ymm5
+; AVX2-NEXT: vperm2i128 {{.*#+}} ymm4 = ymm0[0,1],ymm2[0,1]
+; AVX2-NEXT: vperm2i128 {{.*#+}} ymm5 = ymm1[0,1],ymm3[0,1]
; AVX2-NEXT: vperm2i128 {{.*#+}} ymm0 = ymm0[2,3],ymm2[2,3]
; AVX2-NEXT: vperm2i128 {{.*#+}} ymm1 = ymm1[2,3],ymm3[2,3]
; AVX2-NEXT: vpunpcklqdq {{.*#+}} ymm2 = ymm4[0],ymm5[0],ymm4[2],ymm5[2]
diff --git a/test/DebugInfo/COFF/array-odr-violation.ll b/test/DebugInfo/COFF/array-odr-violation.ll
index 471c18f00afd..1041a90f0343 100644
--- a/test/DebugInfo/COFF/array-odr-violation.ll
+++ b/test/DebugInfo/COFF/array-odr-violation.ll
@@ -65,7 +65,7 @@ attributes #1 = { nounwind readnone }
!llvm.dbg.cu = !{!2, !11}
!llvm.ident = !{!13, !13}
-!llvm.module.flags = !{!14, !18, !19, !20}
+!llvm.module.flags = !{!18, !19, !20}
!0 = !DIGlobalVariableExpression(var: !1)
!1 = distinct !DIGlobalVariable(name: "a", linkageName: "\01?a@@3TYYSTYPE@@A", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
@@ -81,10 +81,6 @@ attributes #1 = { nounwind readnone }
!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !12, producer: "clang version 5.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4)
!12 = !DIFile(filename: "b.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild", checksumkind: CSK_MD5, checksum: "9cfd390d8827beab36769147bb037abc")
!13 = !{!"clang version 5.0.0 "}
-!14 = !{i32 6, !"Linker Options", !15}
-!15 = !{!16, !17}
-!16 = !{!"/DEFAULTLIB:libcmt.lib"}
-!17 = !{!"/DEFAULTLIB:oldnames.lib"}
!18 = !{i32 2, !"CodeView", i32 1}
!19 = !{i32 2, !"Debug Info Version", i32 3}
!20 = !{i32 1, !"PIC Level", i32 2}
diff --git a/test/DebugInfo/COFF/inlining-same-name.ll b/test/DebugInfo/COFF/inlining-same-name.ll
index fda5a6dc6ff5..4a9c9924135d 100644
--- a/test/DebugInfo/COFF/inlining-same-name.ll
+++ b/test/DebugInfo/COFF/inlining-same-name.ll
@@ -39,12 +39,11 @@ define void @main(i32* %i.i) !dbg !16 {
ret void
}
-!llvm.module.flags = !{!0, !1, !2}
+!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!4}
!0 = !{i32 2, !"CodeView", i32 1}
!1 = !{i32 2, !"Debug Info Version", i32 3}
-!2 = !{i32 6, !"Linker Options", !{}}
!4 = distinct !DICompileUnit(language: DW_LANG_D, file: !5, producer: "LDC (http://wiki.dlang.org/LDC)", isOptimized: false, runtimeVersion: 1, emissionKind: FullDebug)
!5 = !DIFile(filename: "opover2.d", directory: "C:\5CLDC\5Cninja-ldc\5C..\5Cldc\5Ctests\5Cd2\5Cdmd-testsuite\5Crunnable")
!6 = !DILocation(line: 302, column: 9, scope: !7, inlinedAt: !15)
diff --git a/test/DebugInfo/Generic/block-asan.ll b/test/DebugInfo/Generic/block-asan.ll
index f1f8b35df27c..73df59bf3d5d 100644
--- a/test/DebugInfo/Generic/block-asan.ll
+++ b/test/DebugInfo/Generic/block-asan.ll
@@ -13,7 +13,7 @@
; Check that the location of the ASAN instrumented __block variable is
; correct.
-; CHECK: !DIExpression(DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24)
+; CHECK: !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24)
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
@@ -79,7 +79,7 @@ attributes #3 = { nounwind }
!19 = !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
!20 = !DIDerivedType(tag: DW_TAG_member, name: "__size", size: 32, align: 32, offset: 160, file: !1, scope: !5, baseType: !19)
!21 = !DIDerivedType(tag: DW_TAG_member, name: "x", size: 32, align: 32, offset: 192, file: !1, scope: !5, baseType: !19)
-!22 = !DIExpression(DW_OP_plus, 8, DW_OP_deref, DW_OP_plus, 24)
+!22 = !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_plus_uconst, 24)
!23 = !DILocation(line: 4, column: 15, scope: !4)
!24 = !DILocation(line: 4, column: 3, scope: !4)
!25 = !DILocation(line: 5, column: 3, scope: !4)
diff --git a/test/DebugInfo/Inputs/dwarfdump-str-offsets-dwp.x86_64.o b/test/DebugInfo/Inputs/dwarfdump-str-offsets-dwp.x86_64.o
new file mode 100644
index 000000000000..b3c73f72d246
--- /dev/null
+++ b/test/DebugInfo/Inputs/dwarfdump-str-offsets-dwp.x86_64.o
Binary files differ
diff --git a/test/DebugInfo/Inputs/dwarfdump-str-offsets.s b/test/DebugInfo/Inputs/dwarfdump-str-offsets.s
index e0a634c7c4a2..f395f4b872c1 100644
--- a/test/DebugInfo/Inputs/dwarfdump-str-offsets.s
+++ b/test/DebugInfo/Inputs/dwarfdump-str-offsets.s
@@ -248,253 +248,3 @@ TU_split_5_type:
.byte 0 # NULL
.byte 0 # NULL
TU_split_5_end:
-# Test object to verify dwarfdump handles v5 string offset tables.
-# We have 2 v5 CUs, a v5 TU, and a split v5 CU and TU.
-#
-# To generate the test object:
-# llvm-mc -triple x86_64-unknown-linux dwarfdump-str-offsets.s -filetype=obj \
-# -o dwarfdump-str-offsets.elf-x86-64
-
- .section .debug_str,"MS",@progbits,1
-str_producer:
- .asciz "Handmade DWARF producer"
-str_CU1:
- .asciz "Compile_Unit_1"
-str_CU1_dir:
- .asciz "/home/test/CU1"
-str_CU2:
- .asciz "Compile_Unit_2"
-str_CU2_dir:
- .asciz "/home/test/CU2"
-str_TU:
- .asciz "Type_Unit"
-str_TU_type:
- .asciz "MyStruct"
-
-# Every unit contributes to the string_offsets table.
- .section .debug_str_offsets,"",@progbits
-# CU1's contribution
- .long .debug_str_offsets_segment0_end-.debug_str_offsets_base0
- .short 5 # DWARF version
- .short 0 # Padding
-.debug_str_offsets_base0:
- .long str_producer
- .long str_CU1
- .long str_CU1_dir
-.debug_str_offsets_segment0_end:
-# CU2's contribution
- .long .debug_str_offsets_segment1_end-.debug_str_offsets_base1
- .short 5 # DWARF version
- .short 0 # Padding
-.debug_str_offsets_base1:
- .long str_producer
- .long str_CU2
- .long str_CU2_dir
-.debug_str_offsets_segment1_end:
-# The TU's contribution
- .long .debug_str_offsets_segment2_end-.debug_str_offsets_base2
- .short 5 # DWARF version
- .short 0 # Padding
-.debug_str_offsets_base2:
- .long str_TU
- .long str_TU_type
-.debug_str_offsets_segment2_end:
-
- .section .debug_str.dwo,"MS",@progbits,1
-dwo_str_CU_5_producer:
- .asciz "Handmade split DWARF producer"
-dwo_str_CU_5_name:
- .asciz "V5_split_compile_unit"
-dwo_str_CU_5_comp_dir:
- .asciz "/home/test/splitCU"
-dwo_str_TU_5:
- .asciz "V5_split_type_unit"
-dwo_str_TU_5_type:
- .asciz "V5_split_Mystruct"
-
- .section .debug_str_offsets.dwo,"",@progbits
-# The split CU's contribution
- .long .debug_dwo_str_offsets_segment0_end-.debug_dwo_str_offsets_base0
- .short 5 # DWARF version
- .short 0 # Padding
-.debug_dwo_str_offsets_base0:
- .long dwo_str_CU_5_producer-.debug_str.dwo
- .long dwo_str_CU_5_name-.debug_str.dwo
- .long dwo_str_CU_5_comp_dir-.debug_str.dwo
-.debug_dwo_str_offsets_segment0_end:
-# The split TU's contribution
- .long .debug_dwo_str_offsets_segment1_end-.debug_dwo_str_offsets_base1
- .short 5 # DWARF version
- .short 0 # Padding
-.debug_dwo_str_offsets_base1:
- .long dwo_str_TU_5-.debug_str.dwo
- .long dwo_str_TU_5_type-.debug_str.dwo
-.debug_dwo_str_offsets_segment1_end:
-
-# All CUs/TUs use the same abbrev section for simplicity.
- .section .debug_abbrev,"",@progbits
- .byte 0x01 # Abbrev code
- .byte 0x11 # DW_TAG_compile_unit
- .byte 0x00 # DW_CHILDREN_no
- .byte 0x25 # DW_AT_producer
- .byte 0x1a # DW_FORM_strx
- .byte 0x03 # DW_AT_name
- .byte 0x1a # DW_FORM_strx
- .byte 0x72 # DW_AT_str_offsets_base
- .byte 0x17 # DW_FORM_sec_offset
- .byte 0x1b # DW_AT_comp_dir
- .byte 0x1a # DW_FORM_strx
- .byte 0x00 # EOM(1)
- .byte 0x00 # EOM(2)
- .byte 0x02 # Abbrev code
- .byte 0x41 # DW_TAG_type_unit
- .byte 0x01 # DW_CHILDREN_yes
- .byte 0x03 # DW_AT_name
- .byte 0x1a # DW_FORM_strx
- .byte 0x72 # DW_AT_str_offsets_base
- .byte 0x17 # DW_FORM_sec_offset
- .byte 0x00 # EOM(1)
- .byte 0x00 # EOM(2)
- .byte 0x03 # Abbrev code
- .byte 0x13 # DW_TAG_structure_type
- .byte 0x00 # DW_CHILDREN_no (no members)
- .byte 0x03 # DW_AT_name
- .byte 0x1a # DW_FORM_strx
- .byte 0x00 # EOM(1)
- .byte 0x00 # EOM(2)
- .byte 0x00 # EOM(3)
-
-# And a .dwo copy for the .dwo sections.
- .section .debug_abbrev.dwo,"",@progbits
- .byte 0x01 # Abbrev code
- .byte 0x11 # DW_TAG_compile_unit
- .byte 0x00 # DW_CHILDREN_no
- .byte 0x25 # DW_AT_producer
- .byte 0x1a # DW_FORM_strx
- .byte 0x03 # DW_AT_name
- .byte 0x1a # DW_FORM_strx
- .byte 0x72 # DW_AT_str_offsets_base
- .byte 0x17 # DW_FORM_sec_offset
- .byte 0x1b # DW_AT_comp_dir
- .byte 0x1a # DW_FORM_strx
- .byte 0x00 # EOM(1)
- .byte 0x00 # EOM(2)
- .byte 0x02 # Abbrev code
- .byte 0x41 # DW_TAG_type_unit
- .byte 0x01 # DW_CHILDREN_yes
- .byte 0x03 # DW_AT_name
- .byte 0x1a # DW_FORM_strx
- .byte 0x72 # DW_AT_str_offsets_base
- .byte 0x17 # DW_FORM_sec_offset
- .byte 0x00 # EOM(1)
- .byte 0x00 # EOM(2)
- .byte 0x03 # Abbrev code
- .byte 0x13 # DW_TAG_structure_type
- .byte 0x00 # DW_CHILDREN_no (no members)
- .byte 0x03 # DW_AT_name
- .byte 0x1a # DW_FORM_strx
- .byte 0x00 # EOM(1)
- .byte 0x00 # EOM(2)
- .byte 0x00 # EOM(3)
-
- .section .debug_info,"",@progbits
-
-# DWARF v5 CU header.
- .long CU1_5_end-CU1_5_version # Length of Unit
-CU1_5_version:
- .short 5 # DWARF version number
- .byte 1 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev # Offset Into Abbrev. Section
-# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
-# DW_AT_str_offsets and DW_AT_compdir.
- .byte 1 # Abbreviation code
- .byte 0 # The index of the producer string
- .byte 1 # The index of the CU name string
- .long .debug_str_offsets_base0
- .byte 2 # The index of the comp dir string
- .byte 0 # NULL
-CU1_5_end:
-
-# DWARF v5 CU header
- .long CU2_5_end-CU2_5_version # Length of Unit
-CU2_5_version:
- .short 5 # DWARF version number
- .byte 1 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev # Offset Into Abbrev. Section
-# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
-# DW_AT_str_offsets and DW_AT_compdir.
- .byte 1 # Abbreviation code
- .byte 0 # The index of the producer string
- .byte 1 # The index of the CU name string
- .long .debug_str_offsets_base1
- .byte 2 # The index of the comp dir string
- .byte 0 # NULL
-CU2_5_end:
-
- .section .debug_types,"",@progbits
-# DWARF v5 Type unit header.
-TU_5_start:
- .long TU_5_end-TU_5_version # Length of Unit
-TU_5_version:
- .short 5 # DWARF version number
- .byte 2 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev # Offset Into Abbrev. Section
- .quad 0x0011223344556677 # Type Signature
- .long TU_5_type-TU_5_start # Type offset
-# The type-unit DIE, which has a name.
- .byte 2 # Abbreviation code
- .byte 0 # Index of the unit type name string
- .long .debug_str_offsets_base2 # offset into the str_offsets section
-# The type DIE, which has a name.
-TU_5_type:
- .byte 3 # Abbreviation code
- .byte 1 # Index of the type name string
- .byte 0 # NULL
- .byte 0 # NULL
-TU_5_end:
-
- .section .debug_info.dwo,"",@progbits
-
-# DWARF v5 split CU header.
- .long CU_split_5_end-CU_split_5_version # Length of Unit
-CU_split_5_version:
- .short 5 # DWARF version number
- .byte 1 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev.dwo # Offset Into Abbrev Section
-# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name,
-# DW_AT_str_offsets and DW_AT_compdir.
- .byte 1 # Abbreviation code
- .byte 0 # The index of the producer string
- .byte 1 # The index of the CU name string
- .long .debug_dwo_str_offsets_base0-.debug_str_offsets.dwo
- .byte 2 # The index of the comp dir string
- .byte 0 # NULL
-CU_split_5_end:
-
- .section .debug_types.dwo,"",@progbits
-
-# DWARF v5 split type unit header.
-TU_split_5_start:
- .long TU_split_5_end-TU_split_5_version # Length of Unit
-TU_split_5_version:
- .short 5 # DWARF version number
- .byte 6 # DWARF Unit Type
- .byte 8 # Address Size (in bytes)
- .long .debug_abbrev.dwo # Offset Into Abbrev Section
- .quad 0x8899aabbccddeeff # Type Signature
- .long TU_split_5_type-TU_split_5_start # Type offset
-# The type-unit DIE, which has a name.
- .byte 2 # Abbreviation code
- .byte 0 # The index of the type unit name string
- .long .debug_dwo_str_offsets_base1-.debug_str_offsets.dwo
-# The type DIE, which has a name.
-TU_split_5_type:
- .byte 3 # Abbreviation code
- .byte 1 # The index of the type name string
- .byte 0 # NULL
- .byte 0 # NULL
-TU_split_5_end:
diff --git a/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc b/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc
index 966a465f9046..6c506381aa5d 100644
--- a/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc
+++ b/test/DebugInfo/Inputs/dwarfdump-test-zlib.cc
@@ -22,6 +22,7 @@ int main() {
// $ cp dwarfdump-test-zlib.cc /tmp/dbginfo
// $ cd /tmp/dbginfo
// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib -o dwarfdump-test-zlib.elf-x86-64
+// $ clang++ -g dwarfdump-test-zlib.cc -Wa,--compress-debug-sections=zlib -c -o dwarfdump-test-zlib.o.elf-x86-64
// $ clang++ -g dwarfdump-test-zlib.cc -Wl,--compress-debug-sections=zlib-gnu -o dwarfdump-test-zlibgnu.elf-x86-64
// llvm-readobj -sections can be used to see that outputs really contain the compressed sections, also output in both
-// cases is slightly smaller, that is because of compression. \ No newline at end of file
+// cases is slightly smaller, that is because of compression.
diff --git a/test/DebugInfo/Inputs/dwarfdump-test-zlib.o.elf-x86-64 b/test/DebugInfo/Inputs/dwarfdump-test-zlib.o.elf-x86-64
new file mode 100644
index 000000000000..55f5cb0d157c
--- /dev/null
+++ b/test/DebugInfo/Inputs/dwarfdump-test-zlib.o.elf-x86-64
Binary files differ
diff --git a/test/DebugInfo/MIR/ARM/split-superreg-complex.mir b/test/DebugInfo/MIR/ARM/split-superreg-complex.mir
index 2e8d9977a649..0ebde3c1eb35 100644
--- a/test/DebugInfo/MIR/ARM/split-superreg-complex.mir
+++ b/test/DebugInfo/MIR/ARM/split-superreg-complex.mir
@@ -57,7 +57,7 @@
!17 = !{!18}
!18 = !DISubrange(count: 4)
!19 = !DILocation(line: 4, column: 13, scope: !9)
- !20 = !DIExpression(DW_OP_plus, 1, DW_OP_minus, 1)
+ !20 = !DIExpression(DW_OP_plus_uconst, 1, DW_OP_constu, 1, DW_OP_minus)
!21 = !DILocation(line: 4, column: 7, scope: !9)
!22 = !DILocation(line: 5, column: 9, scope: !9)
!23 = !DILocation(line: 5, column: 18, scope: !9)
diff --git a/test/DebugInfo/PDB/Inputs/unknown-symbol.yaml b/test/DebugInfo/PDB/Inputs/unknown-symbol.yaml
new file mode 100644
index 000000000000..a2966c437879
--- /dev/null
+++ b/test/DebugInfo/PDB/Inputs/unknown-symbol.yaml
@@ -0,0 +1,10 @@
+---
+DbiStream:
+ Modules:
+ - Module: unknown-symbol.yaml
+ Modi:
+ Records:
+ - Kind: S_ANNOTATION
+ UnknownSym:
+ Data: 123456789ABCDEF0
+...
diff --git a/test/DebugInfo/PDB/pdb-unknown-symbol.test b/test/DebugInfo/PDB/pdb-unknown-symbol.test
new file mode 100644
index 000000000000..3d2547ee51a9
--- /dev/null
+++ b/test/DebugInfo/PDB/pdb-unknown-symbol.test
@@ -0,0 +1,6 @@
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/unknown-symbol.yaml
+; RUN: llvm-pdbutil pdb2yaml -minimal -module-syms -no-file-headers %t.pdb | FileCheck %s
+
+CHECK: - Kind: S_ANNOTATION
+CHECK: UnknownSym:
+CHECK: Data: 123456789ABCDEF0
diff --git a/test/DebugInfo/PDB/pdb-yaml-types.test b/test/DebugInfo/PDB/pdb-yaml-types.test
deleted file mode 100644
index f65d9edaa549..000000000000
--- a/test/DebugInfo/PDB/pdb-yaml-types.test
+++ /dev/null
@@ -1,74 +0,0 @@
-RUN: llvm-pdbutil pdb2yaml -tpi-stream %p/Inputs/big-read.pdb > %t.yaml
-RUN: FileCheck -check-prefix=YAML %s < %t.yaml
-RUN: llvm-pdbutil yaml2pdb %t.yaml -pdb %t.pdb
-RUN: llvm-pdbutil raw -tpi-records %t.pdb | FileCheck %s --check-prefix=PDB
-
-Only verify the beginning of the type stream.
-
-YAML: TpiStream:
-YAML-NEXT: Version: VC80
-YAML-NEXT: Records:
-YAML-NEXT: - Kind: LF_ARGLIST
-YAML-NEXT: ArgList:
-YAML-NEXT: ArgIndices: [ ]
-YAML-NEXT: - Kind: LF_PROCEDURE
-YAML-NEXT: Procedure:
-YAML-NEXT: ReturnType: 3
-YAML-NEXT: CallConv: NearC
-YAML-NEXT: Options: [ None ]
-YAML-NEXT: ParameterCount: 0
-YAML-NEXT: ArgumentList: 4096
-YAML-NEXT: - Kind: LF_PROCEDURE
-YAML-NEXT: Procedure:
-YAML-NEXT: ReturnType: 116
-YAML-NEXT: CallConv: NearC
-YAML-NEXT: Options: [ None ]
-YAML-NEXT: ParameterCount: 0
-YAML-NEXT: ArgumentList: 4096
-
-This test is mostly checking to make sure we include the type index offset
-table, and eventually hash codes. The type index offsets should be similar to
-what are already present in big-read.pdb.
-
-PDB: Type Info Stream (TPI) {
-PDB-NEXT: TPI Version: 20040203
-PDB-NEXT: Record count: 728
-PDB-NEXT: Records [
-PDB-NEXT: {
-PDB-NEXT: ArgList (0x1000) {
-PDB-NEXT: TypeLeafKind: LF_ARGLIST (0x1201)
-PDB-NEXT: NumArgs: 0
-PDB-NEXT: Arguments [
-PDB-NEXT: ]
-PDB-NEXT: }
-PDB-NEXT: }
-PDB-NEXT: {
-PDB-NEXT: Procedure (0x1001) {
-PDB-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008)
-PDB-NEXT: ReturnType: void (0x3)
-PDB-NEXT: CallingConvention: NearC (0x0)
-PDB-NEXT: FunctionOptions [ (0x0)
-PDB-NEXT: ]
-PDB-NEXT: NumParameters: 0
-PDB-NEXT: ArgListType: () (0x1000)
-PDB-NEXT: }
-PDB-NEXT: }
-PDB-NEXT: {
-PDB-NEXT: Procedure (0x1002) {
-PDB-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008)
-PDB-NEXT: ReturnType: int (0x74)
-PDB-NEXT: CallingConvention: NearC (0x0)
-PDB-NEXT: FunctionOptions [ (0x0)
-PDB-NEXT: ]
-PDB-NEXT: NumParameters: 0
-PDB-NEXT: ArgListType: () (0x1000)
-PDB-NEXT: }
-PDB-NEXT: }
-...
-PDB: TypeIndexOffsets [
-PDB-NEXT: Index: 0x1000, Offset: 0
-PDB-NEXT: Index: 0x106c, Offset: 8,116
-PDB-NEXT: Index: 0x1118, Offset: 16,372
-PDB-NEXT: Index: 0x11df, Offset: 24,564
-PDB-NEXT: Index: 0x128e, Offset: 32,752
-PDB-NEXT: ]
diff --git a/test/DebugInfo/PDB/pdbdump-debug-subsections.test b/test/DebugInfo/PDB/pdbdump-debug-subsections.test
index 52f7bb52da2a..4338f11587ce 100644
--- a/test/DebugInfo/PDB/pdbdump-debug-subsections.test
+++ b/test/DebugInfo/PDB/pdbdump-debug-subsections.test
@@ -1,6 +1,5 @@
; RUN: llvm-pdbutil yaml2pdb -pdb=%t.pdb %p/Inputs/debug-subsections.yaml
; RUN: llvm-pdbutil pdb2yaml -all -no-file-headers %t.pdb | FileCheck --check-prefix=YAML %s
-; RUN: llvm-pdbutil raw -subsections=all %t.pdb | FileCheck --check-prefix=RAW %s
YAML: Modules:
YAML-NEXT: - Module: Foo.obj
@@ -61,150 +60,7 @@ YAML-NEXT: EndDelta: 0
YAML-NEXT: Columns:
YAML-NEXT: - !InlineeLines
YAML-NEXT: HasExtraFiles: false
-YAML-NEXT: Sites:
+YAML-NEXT: Sites:
YAML-NEXT: - FileName: 'f:\dd\externalapis\windows\10\sdk\inc\winerror.h'
YAML-NEXT: LineNum: 26950
YAML-NEXT: Inlinee: 22767
-
-
-RAW: DBI Stream {
-RAW: Modules [
-RAW-NEXT: {
-RAW-NEXT: Name: Foo.obj
-RAW: Subsections [
-RAW-NEXT: CrossModuleExports [
-RAW-NEXT: Export {
-RAW-NEXT: Local: 0x12F4
-RAW-NEXT: Global: 0x2443
-RAW-NEXT: }
-RAW-NEXT: Export {
-RAW-NEXT: Local: 0x80001083
-RAW-NEXT: Global: 0x23A3
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: ]
-RAW-NEXT: }
-RAW-NEXT: {
-RAW-NEXT: Name: Bar.obj
-RAW: Subsections [
-RAW-NEXT: CrossModuleExports [
-RAW-NEXT: Export {
-RAW-NEXT: Local: 0x10A9
-RAW-NEXT: Global: 0x17D1
-RAW-NEXT: }
-RAW-NEXT: Export {
-RAW-NEXT: Local: 0x10C9
-RAW-NEXT: Global: 0x1245
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: CrossModuleImports [
-RAW-NEXT: ModuleImport {
-RAW-NEXT: Module: Foo.obj
-RAW-NEXT: Imports: [0x12F4, 0x80001083]
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: ]
-RAW-NEXT: }
-RAW-NEXT: {
-RAW-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-RAW: Subsections [
-RAW-NEXT: FileChecksums {
-RAW-NEXT: Checksum {
-RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-RAW-NEXT: Kind: MD5 (0x1)
-RAW-NEXT: Checksum (
-RAW-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
-RAW-NEXT: )
-RAW-NEXT: }
-RAW-NEXT: Checksum {
-RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
-RAW-NEXT: Kind: MD5 (0x1)
-RAW-NEXT: Checksum (
-RAW-NEXT: 0000: 1154D69F 5B265019 6E1FC34F 4134E56B |.T..[&P.n..OA4.k|
-RAW-NEXT: )
-RAW-NEXT: }
-RAW-NEXT: }
-RAW-NEXT: Lines {
-RAW-NEXT: RelocSegment: 1
-RAW-NEXT: RelocOffset: 100016
-RAW-NEXT: CodeSize: 10
-RAW-NEXT: HasColumns: No
-RAW-NEXT: FileEntry {
-RAW-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-RAW-NEXT: Line {
-RAW-NEXT: Offset: 0
-RAW-NEXT: LineNumberStart: 5
-RAW-NEXT: EndDelta: 0
-RAW-NEXT: IsStatement: Yes
-RAW-NEXT: }
-RAW-NEXT: Line {
-RAW-NEXT: Offset: 3
-RAW-NEXT: LineNumberStart: 6
-RAW-NEXT: EndDelta: 0
-RAW-NEXT: IsStatement: Yes
-RAW-NEXT: }
-RAW-NEXT: Line {
-RAW-NEXT: Offset: 8
-RAW-NEXT: LineNumberStart: 7
-RAW-NEXT: EndDelta: 0
-RAW-NEXT: IsStatement: Yes
-RAW-NEXT: }
-RAW-NEXT: }
-RAW-NEXT: }
-RAW-NEXT: InlineeLines {
-RAW-NEXT: HasExtraFiles: No
-RAW-NEXT: Lines [
-RAW-NEXT: Inlinee {
-RAW-NEXT: FileName: f:\dd\externalapis\windows\10\sdk\inc\winerror.h
-RAW-NEXT: Function {
-RAW-NEXT: Index: 0x58ef (unknown function)
-RAW-NEXT: }
-RAW-NEXT: SourceLine: 26950
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: }
-RAW-NEXT: {
-RAW-NEXT: Name: ObjFileSubsections
-RAW-NEXT: Debug Stream Index: 11
-RAW-NEXT: Object File Name: ObjFileSubsections
-RAW-NEXT: Num Files: 0
-RAW-NEXT: Source File Name Idx: 0
-RAW-NEXT: Pdb File Name Idx: 0
-RAW-NEXT: Line Info Byte Size: 0
-RAW-NEXT: C13 Line Info Byte Size: 116
-RAW-NEXT: Symbol Byte Size: 4
-RAW-NEXT: Type Server Index: 0
-RAW-NEXT: Has EC Info: No
-RAW-NEXT: Subsections [
-RAW-NEXT: String Table [
-RAW-NEXT: String1
-RAW-NEXT: String2
-RAW-NEXT: String3
-RAW-NEXT: ]
-RAW-NEXT: Symbols [
-RAW-NEXT: {
-RAW-NEXT: ObjectName {
-RAW-NEXT: Signature: 0x0
-RAW-NEXT: ObjectName: ObjFileSubsections
-RAW-NEXT: }
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: FrameData [
-RAW-NEXT: Frame {
-RAW-NEXT: Rva: 6
-RAW-NEXT: CodeSize: 1
-RAW-NEXT: LocalSize: 2
-RAW-NEXT: ParamsSize: 4
-RAW-NEXT: MaxStackSize: 3
-RAW-NEXT: FrameFunc: MyFunc
-RAW-NEXT: PrologSize: 5
-RAW-NEXT: SavedRegsSize: 7
-RAW-NEXT: Flags: 0
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: ]
-RAW-NEXT: }
-RAW-NEXT: ]
-RAW-NEXT: }
diff --git a/test/DebugInfo/PDB/pdbdump-headers.test b/test/DebugInfo/PDB/pdbdump-headers.test
index 82fe91dd20aa..fa9a25108fac 100644
--- a/test/DebugInfo/PDB/pdbdump-headers.test
+++ b/test/DebugInfo/PDB/pdbdump-headers.test
@@ -1,2901 +1,1082 @@
-; RUN: llvm-pdbutil raw -headers -string-table -tpi-records -tpi-record-bytes -module-syms \
-; RUN: -sym-record-bytes -globals -publics -module-files \
-; RUN: -stream-summary -stream-blocks -ipi-records -ipi-record-bytes \
-; RUN: -section-contribs -section-map -section-headers -subsections=all \
-; RUN: -tpi-hash -fpo -page-stats %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
; RUN: llvm-pdbutil raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
-; RUN: llvm-pdbutil raw -headers -modules -module-files \
+; RUN: llvm-pdbutil raw -summary -modules -files \
; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
-; RUN: not llvm-pdbutil raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
+; RUN: not llvm-pdbutil raw -summary %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
-; EMPTY: FileHeaders {
-; EMPTY-NEXT: BlockSize: 4096
-; EMPTY-NEXT: FreeBlockMap: 2
-; EMPTY-NEXT: NumBlocks: 25
-; EMPTY-NEXT: NumDirectoryBytes: 136
-; EMPTY-NEXT: Unknown1: 0
-; EMPTY-NEXT: BlockMapAddr: 24
-; EMPTY-NEXT: NumDirectoryBlocks: 1
-; EMPTY-NEXT: DirectoryBlocks: [23]
-; EMPTY-NEXT: NumStreams: 17
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Streams [
-; EMPTY-NEXT: Stream 0: [Old MSF Directory] (40 bytes)
-; EMPTY-NEXT: Stream 1: [PDB Stream] (118 bytes)
-; EMPTY-NEXT: Stream 2: [TPI Stream] (5392 bytes)
-; EMPTY-NEXT: Stream 3: [DBI Stream] (739 bytes)
-; EMPTY-NEXT: Stream 4: [IPI Stream] (784 bytes)
-; EMPTY-NEXT: Stream 5: [Named Stream "/LinkInfo"] (0 bytes)
-; EMPTY-NEXT: Stream 6: [Global Symbol Hash] (556 bytes)
-; EMPTY-NEXT: Stream 7: [Public Symbol Hash] (604 bytes)
-; EMPTY-NEXT: Stream 8: [Public Symbol Records] (104 bytes)
-; EMPTY-NEXT: Stream 9: [Named Stream "/src/headerblock"] (0 bytes)
-; EMPTY-NEXT: Stream 10: [Section Header Data] (160 bytes)
-; EMPTY-NEXT: Stream 11: [New FPO Data] (32 bytes)
-; EMPTY-NEXT: Stream 12: [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"] (308 bytes)
-; EMPTY-NEXT: Stream 13: [Named Stream "/names"] (239 bytes)
-; EMPTY-NEXT: Stream 14: [Module "* Linker *"] (520 bytes)
-; EMPTY-NEXT: Stream 15: [TPI Hash] (308 bytes)
-; EMPTY-NEXT: Stream 16: [IPI Hash] (68 bytes)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Msf Free Pages: [3, 4, 5, 8, 9]
-; EMPTY-NEXT: Orphaned Pages: []
-; EMPTY-NEXT: Multiply Used Pages: []
-; EMPTY-NEXT: Use After Free Pages: []
-; EMPTY-NEXT: StreamBlocks [
-; EMPTY-NEXT: Stream 0: [8]
-; EMPTY-NEXT: Stream 1: [19]
-; EMPTY-NEXT: Stream 2: [18, 17]
-; EMPTY-NEXT: Stream 3: [14]
-; EMPTY-NEXT: Stream 4: [20]
-; EMPTY-NEXT: Stream 5: []
-; EMPTY-NEXT: Stream 6: [11]
-; EMPTY-NEXT: Stream 7: [13]
-; EMPTY-NEXT: Stream 8: [12]
-; EMPTY-NEXT: Stream 9: []
-; EMPTY-NEXT: Stream 10: [10]
-; EMPTY-NEXT: Stream 11: [15]
-; EMPTY-NEXT: Stream 12: [6]
-; EMPTY-NEXT: Stream 13: [16]
-; EMPTY-NEXT: Stream 14: [7]
-; EMPTY-NEXT: Stream 15: [21]
-; EMPTY-NEXT: Stream 16: [22]
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: String Table {
-; EMPTY-NEXT: 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)'
-; EMPTY-NEXT: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
-; EMPTY-NEXT: '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = '
-; EMPTY-NEXT: }
-; EMPTY-NEXT: PDB Stream {
-; EMPTY-NEXT: Version: 20000404
-; EMPTY-NEXT: Signature: 0x54E507E2
-; EMPTY-NEXT: Age: 1
-; EMPTY-NEXT: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
-; EMPTY-NEXT: Features: 0x1
-; EMPTY-NEXT: Named Streams {
-; EMPTY-NEXT: /names: 13
-; EMPTY-NEXT: /LinkInfo: 5
-; EMPTY-NEXT: /src/headerblock: 9
-; EMPTY-NEXT: }
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Type Info Stream (TPI) {
-; EMPTY-NEXT: TPI Version: 20040203
-; EMPTY-NEXT: Record count: 75
-; EMPTY-NEXT: Records [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: ArgList (0x1000) {
-; EMPTY-NEXT: TypeLeafKind: LF_ARGLIST (0x1201)
-; EMPTY-NEXT: NumArgs: 0
-; EMPTY-NEXT: Arguments [
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 |....|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Procedure (0x1001) {
-; EMPTY-NEXT: TypeLeafKind: LF_PROCEDURE (0x1008)
-; EMPTY-NEXT: ReturnType: int (0x74)
-; EMPTY-NEXT: CallingConvention: NearC (0x0)
-; EMPTY-NEXT: FunctionOptions [ (0x0)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: NumParameters: 0
-; EMPTY-NEXT: ArgListType: () (0x1000)
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 74000000 00000000 00100000 |t...........|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: FieldList (0x1002) {
-; EMPTY-NEXT: TypeLeafKind: LF_FIELDLIST (0x1203)
-; EMPTY-NEXT: Enumerator {
-; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502)
-; EMPTY-NEXT: AccessSpecifier: Public (0x3)
-; EMPTY-NEXT: EnumValue: 1
-; EMPTY-NEXT: Name: apartment
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Enumerator {
-; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502)
-; EMPTY-NEXT: AccessSpecifier: Public (0x3)
-; EMPTY-NEXT: EnumValue: 2
-; EMPTY-NEXT: Name: single
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Enumerator {
-; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502)
-; EMPTY-NEXT: AccessSpecifier: Public (0x3)
-; EMPTY-NEXT: EnumValue: 3
-; EMPTY-NEXT: Name: free
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Enumerator {
-; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502)
-; EMPTY-NEXT: AccessSpecifier: Public (0x3)
-; EMPTY-NEXT: EnumValue: 4
-; EMPTY-NEXT: Name: neutral
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Enumerator {
-; EMPTY-NEXT: TypeLeafKind: LF_ENUMERATE (0x1502)
-; EMPTY-NEXT: AccessSpecifier: Public (0x3)
-; EMPTY-NEXT: EnumValue: 5
-; EMPTY-NEXT: Name: both
-; EMPTY-NEXT: }
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 02150300 01006170 6172746D 656E7400 |......apartment.|
-; EMPTY-NEXT: 0010: 02150300 02007369 6E676C65 00F3F2F1 |......single....|
-; EMPTY-NEXT: 0020: 02150300 03006672 656500F1 02150300 |......free......|
-; EMPTY-NEXT: 0030: 04006E65 75747261 6C00F2F1 02150300 |..neutral.......|
-; EMPTY-NEXT: 0040: 0500626F 746800F1 |..both..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY: Hash {
-; EMPTY-NEXT: Number of Hash Buckets: 262143
-; EMPTY-NEXT: Hash Key Size: 4
-; EMPTY-NEXT: Values: [205956, 163561, 59811, 208239, 16377, 247078, 194342, 254156, 194536, 167492, 185421, 119540, 261871, 198119, 48056, 251486, 134580, 148190, 113636, 53336, 55779, 220695, 198114, 148734, 81128, 60158, 217249, 174209, 159978, 249504, 141941, 238785, 6214, 94935, 151449, 135589, 73373, 96512, 254299, 17744, 239514, 173189, 130544, 204437, 238560, 144673, 115151, 197306, 256035, 101096, 231280, 52156, 48854, 170035, 177041, 102745, 16947, 183703, 98548, 35693, 171328, 203640, 139292, 49018, 43821, 202555, 165040, 215835, 142625, 52534, 44186, 103930, 110942, 17991, 213215]
-; EMPTY-NEXT: Adjusters [
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: TypeIndexOffsets [
-; EMPTY-NEXT: Index: 0x1000, Offset: 0
-; EMPTY-NEXT: ]
-; EMPTY: Type Info Stream (IPI) {
-; EMPTY-NEXT: IPI Version: 20040203
-; EMPTY-NEXT: Record count: 15
-; EMPTY-NEXT: Records [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: UdtModSourceLine (0x1000) {
-; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; EMPTY-NEXT: UDT: __vc_attributes::threadingAttribute (0x100B)
-; EMPTY-NEXT: SourceFile: <unknown simple type> (0x1)
-; EMPTY-NEXT: LineNumber: 481
-; EMPTY-NEXT: Module: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 0B100000 01000000 E1010000 0100F2F1 |................|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: UdtModSourceLine (0x1001) {
-; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; EMPTY-NEXT: UDT: __vc_attributes::event_receiverAttribute (0x1017)
-; EMPTY-NEXT: SourceFile: <unknown simple type> (0x1)
-; EMPTY-NEXT: LineNumber: 194
-; EMPTY-NEXT: Module: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 17100000 01000000 C2000000 0100F2F1 |................|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: UdtModSourceLine (0x1002) {
-; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; EMPTY-NEXT: UDT: __vc_attributes::aggregatableAttribute (0x1021)
-; EMPTY-NEXT: SourceFile: <unknown simple type> (0x1)
-; EMPTY-NEXT: LineNumber: 603
-; EMPTY-NEXT: Module: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 21100000 01000000 5B020000 0100F2F1 |!.......[.......|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: UdtModSourceLine (0x1003) {
-; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; EMPTY-NEXT: UDT: __vc_attributes::event_sourceAttribute (0x102C)
-; EMPTY-NEXT: SourceFile: <unknown simple type> (0x1)
-; EMPTY-NEXT: LineNumber: 1200
-; EMPTY-NEXT: Module: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 2C100000 01000000 B0040000 0100F2F1 |,...............|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: UdtModSourceLine (0x1004) {
-; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; EMPTY-NEXT: UDT: __vc_attributes::moduleAttribute (0x103A)
-; EMPTY-NEXT: SourceFile: <unknown simple type> (0x1)
-; EMPTY-NEXT: LineNumber: 540
-; EMPTY-NEXT: Module: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 3A100000 01000000 1C020000 0100F2F1 |:...............|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: UdtModSourceLine (0x1005) {
-; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; EMPTY-NEXT: UDT: __vc_attributes::helper_attributes::usageAttribute (0x1042)
-; EMPTY-NEXT: SourceFile: <unknown simple type> (0x1)
-; EMPTY-NEXT: LineNumber: 108
-; EMPTY-NEXT: Module: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 42100000 01000000 6C000000 0100F2F1 |B.......l.......|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: UdtModSourceLine (0x1006) {
-; EMPTY-NEXT: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; EMPTY-NEXT: UDT: __vc_attributes::helper_attributes::v1_alttypeAttribute (0x104A)
-; EMPTY-NEXT: SourceFile: <unknown simple type> (0x1)
-; EMPTY-NEXT: LineNumber: 96
-; EMPTY-NEXT: Module: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 4A100000 01000000 60000000 0100F2F1 |J.......`.......|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: StringId (0x1007) {
-; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605)
-; EMPTY-NEXT: Id: 0x0
-; EMPTY-NEXT: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 643A5C73 72635C6C 6C766D5C |....d:\src\llvm\|
-; EMPTY-NEXT: 0010: 74657374 5C446562 7567496E 666F5C50 |test\DebugInfo\P|
-; EMPTY-NEXT: 0020: 44425C49 6E707574 7300F2F1 |DB\Inputs...|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: StringId (0x1008) {
-; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605)
-; EMPTY-NEXT: Id: 0x0
-; EMPTY-NEXT: StringData: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 433A5C50 726F6772 616D2046 |....C:\Program F|
-; EMPTY-NEXT: 0010: 696C6573 20287838 36295C4D 6963726F |iles (x86)\Micro|
-; EMPTY-NEXT: 0020: 736F6674 20566973 75616C20 53747564 |soft Visual Stud|
-; EMPTY-NEXT: 0030: 696F2031 322E305C 56435C42 494E5C63 |io 12.0\VC\BIN\c|
-; EMPTY-NEXT: 0040: 6C2E6578 6500F2F1 |l.exe...|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: StringId (0x1009) {
-; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605)
-; EMPTY-NEXT: Id: 0x0
-; EMPTY-NEXT: StringData: empty.cpp
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 656D7074 792E6370 7000F2F1 |....empty.cpp...|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: StringId (0x100A) {
-; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605)
-; EMPTY-NEXT: Id: 0x0
-; EMPTY-NEXT: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 643A5C73 72635C6C 6C766D5C |....d:\src\llvm\|
-; EMPTY-NEXT: 0010: 74657374 5C446562 7567496E 666F5C50 |test\DebugInfo\P|
-; EMPTY-NEXT: 0020: 44425C49 6E707574 735C7663 3132302E |DB\Inputs\vc120.|
-; EMPTY-NEXT: 0030: 70646200 |pdb.|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: StringId (0x100B) {
-; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605)
-; EMPTY-NEXT: Id: 0x0
-; EMPTY-NEXT: StringData: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 2D5A6920 2D4D5420 2D492243 |....-Zi -MT -I"C|
-; EMPTY-NEXT: 0010: 3A5C5072 6F677261 6D204669 6C657320 |:\Program Files |
-; EMPTY-NEXT: 0020: 28783836 295C4D69 63726F73 6F667420 |(x86)\Microsoft |
-; EMPTY-NEXT: 0030: 56697375 616C2053 74756469 6F203132 |Visual Studio 12|
-; EMPTY-NEXT: 0040: 2E305C56 435C494E 434C5544 4522202D |.0\VC\INCLUDE" -|
-; EMPTY-NEXT: 0050: 4922433A 5C50726F 6772616D 2046696C |I"C:\Program Fil|
-; EMPTY-NEXT: 0060: 65732028 78383629 5C4D6963 726F736F |es (x86)\Microso|
-; EMPTY-NEXT: 0070: 66742056 69737561 6C205374 7564696F |ft Visual Studio|
-; EMPTY-NEXT: 0080: 2031322E 305C5643 5C41544C 4D46435C | 12.0\VC\ATLMFC\|
-; EMPTY-NEXT: 0090: 494E434C 55444522 202D4922 433A5C50 |INCLUDE" -I"C:\P|
-; EMPTY-NEXT: 00A0: 726F6772 616D2046 696C6573 20287838 |rogram Files (x8|
-; EMPTY-NEXT: 00B0: 36295C57 696E646F 7773204B 6974735C |6)\Windows Kits\|
-; EMPTY-NEXT: 00C0: 382E315C 696E636C 7564655C 73686172 |8.1\include\shar|
-; EMPTY-NEXT: 00D0: 65642220 2D492243 3A5C5072 6F677261 |ed" -I"C:\Progra|
-; EMPTY-NEXT: 00E0: 6D204669 6C657320 28783836 295C5769 |m Files (x86)\Wi|
-; EMPTY-NEXT: 00F0: 6E646F77 7300F2F1 |ndows...|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: StringList (0x100C) {
-; EMPTY-NEXT: TypeLeafKind: LF_SUBSTR_LIST (0x1604)
-; EMPTY-NEXT: NumStrings: 1
-; EMPTY-NEXT: Strings [
-; EMPTY-NEXT: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 01000000 0B100000 |........|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: StringId (0x100D) {
-; EMPTY-NEXT: TypeLeafKind: LF_STRING_ID (0x1605)
-; EMPTY-NEXT: Id: "-Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows" (0x100C)
-; EMPTY-NEXT: StringData: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 0C100000 204B6974 735C382E 315C696E |.... Kits\8.1\in|
-; EMPTY-NEXT: 0010: 636C7564 655C756D 22202D49 22433A5C |clude\um" -I"C:\|
-; EMPTY-NEXT: 0020: 50726F67 72616D20 46696C65 73202878 |Program Files (x|
-; EMPTY-NEXT: 0030: 3836295C 57696E64 6F777320 4B697473 |86)\Windows Kits|
-; EMPTY-NEXT: 0040: 5C382E31 5C696E63 6C756465 5C77696E |\8.1\include\win|
-; EMPTY-NEXT: 0050: 72742220 2D545020 2D5800F1 |rt" -TP -X..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: BuildInfo (0x100E) {
-; EMPTY-NEXT: TypeLeafKind: LF_BUILDINFO (0x1603)
-; EMPTY-NEXT: NumArgs: 5
-; EMPTY-NEXT: Arguments [
-; EMPTY-NEXT: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs (0x1007)
-; EMPTY-NEXT: ArgType: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe (0x1008)
-; EMPTY-NEXT: ArgType: empty.cpp (0x1009)
-; EMPTY-NEXT: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb (0x100A)
-; EMPTY-NEXT: ArgType: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X (0x100D)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 05000710 00000810 00000910 00000A10 |................|
-; EMPTY-NEXT: 0010: 00000D10 0000F2F1 |........|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: TypeIndexOffsets [
-; EMPTY-NEXT: Index: 0x1000, Offset: 0
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY: DBI Stream {
-; EMPTY-NEXT: Dbi Version: 19990903
-; EMPTY-NEXT: Age: 1
-; EMPTY-NEXT: Incremental Linking: Yes
-; EMPTY-NEXT: Has CTypes: No
-; EMPTY-NEXT: Is Stripped: No
-; EMPTY-NEXT: Machine Type: x86
-; EMPTY-NEXT: Symbol Record Stream Index: 8
-; EMPTY-NEXT: Public Symbol Stream Index: 7
-; EMPTY-NEXT: Global Symbol Stream Index: 6
-; EMPTY-NEXT: Toolchain Version: 12.0
-; EMPTY-NEXT: mspdb120.dll version: 12.0.31101
-; EMPTY-NEXT: Modules [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; EMPTY-NEXT: Debug Stream Index: 12
-; EMPTY-NEXT: Object File Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; EMPTY-NEXT: Num Files: 1
-; EMPTY-NEXT: Source File Name Idx: 0
-; EMPTY-NEXT: Pdb File Name Idx: 0
-; EMPTY-NEXT: Line Info Byte Size: 0
-; EMPTY-NEXT: C13 Line Info Byte Size: 88
-; EMPTY-NEXT: Symbol Byte Size: 208
-; EMPTY-NEXT: Type Server Index: 0
-; EMPTY-NEXT: Has EC Info: No
-; EMPTY-NEXT: 1 Contributing Source Files [
-; EMPTY-NEXT: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Symbols [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: ObjectName {
-; EMPTY-NEXT: Signature: 0x0
-; EMPTY-NEXT: ObjectName: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 643A5C73 72635C6C 6C766D5C |....d:\src\llvm\|
-; EMPTY-NEXT: 0010: 74657374 5C446562 7567496E 666F5C50 |test\DebugInfo\P|
-; EMPTY-NEXT: 0020: 44425C49 6E707574 735C656D 7074792E |DB\Inputs\empty.|
-; EMPTY-NEXT: 0030: 6F626A00 |obj.|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: CompilerFlags3 {
-; EMPTY-NEXT: Language: Cpp (0x1)
-; EMPTY-NEXT: Flags [ (0x2000)
-; EMPTY-NEXT: SecurityChecks (0x2000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Machine: Pentium3 (0x7)
-; EMPTY-NEXT: FrontendVersion: 18.0.31101.0
-; EMPTY-NEXT: BackendVersion: 18.0.31101.0
-; EMPTY-NEXT: VersionName: Microsoft (R) Optimizing Compiler
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 01200000 07001200 00007D79 00001200 |. ........}y....|
-; EMPTY-NEXT: 0010: 00007D79 00004D69 63726F73 6F667420 |..}y..Microsoft |
-; EMPTY-NEXT: 0020: 28522920 4F707469 6D697A69 6E672043 |(R) Optimizing C|
-; EMPTY-NEXT: 0030: 6F6D7069 6C657200 |ompiler.|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: ProcStart {
-; EMPTY-NEXT: Kind: S_GPROC32 (0x1110)
-; EMPTY-NEXT: PtrParent: 0x0
-; EMPTY-NEXT: PtrEnd: 0xC4
-; EMPTY-NEXT: PtrNext: 0x0
-; EMPTY-NEXT: CodeSize: 0xA
-; EMPTY-NEXT: DbgStart: 0x3
-; EMPTY-NEXT: DbgEnd: 0x8
-; EMPTY-NEXT: FunctionType: int () (0x1001)
-; EMPTY-NEXT: Segment: 0x1
-; EMPTY-NEXT: Flags [ (0x1)
-; EMPTY-NEXT: HasFP (0x1)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: DisplayName: main
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 C4000000 00000000 0A000000 |................|
-; EMPTY-NEXT: 0010: 03000000 08000000 01100000 10000000 |................|
-; EMPTY-NEXT: 0020: 0100016D 61696E00 |...main.|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: FrameProc {
-; EMPTY-NEXT: TotalFrameBytes: 0x0
-; EMPTY-NEXT: PaddingFrameBytes: 0x0
-; EMPTY-NEXT: OffsetToPadding: 0x0
-; EMPTY-NEXT: BytesOfCalleeSavedRegisters: 0x0
-; EMPTY-NEXT: OffsetOfExceptionHandler: 0x0
-; EMPTY-NEXT: SectionIdOfExceptionHandler: 0x0
-; EMPTY-NEXT: Flags [ (0x128200)
-; EMPTY-NEXT: AsynchronousExceptionHandling (0x200)
-; EMPTY-NEXT: OptimizedForSpeed (0x100000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
-; EMPTY-NEXT: 0010: 00000000 00000082 12000000 |............|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: BlockEnd {
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: BuildInfo {
-; EMPTY-NEXT: BuildId: 4110
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 0E100000 |....|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Subsections [
-; EMPTY-NEXT: Lines {
-; EMPTY-NEXT: RelocSegment: 1
-; EMPTY-NEXT: RelocOffset: 16
-; EMPTY-NEXT: CodeSize: 10
-; EMPTY-NEXT: HasColumns: No
-; EMPTY-NEXT: FileEntry {
-; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-; EMPTY-NEXT: Line {
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: LineNumberStart: 5
-; EMPTY-NEXT: EndDelta: 0
-; EMPTY-NEXT: IsStatement: Yes
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Line {
-; EMPTY-NEXT: Offset: 3
-; EMPTY-NEXT: LineNumberStart: 6
-; EMPTY-NEXT: EndDelta: 0
-; EMPTY-NEXT: IsStatement: Yes
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Line {
-; EMPTY-NEXT: Offset: 8
-; EMPTY-NEXT: LineNumberStart: 7
-; EMPTY-NEXT: EndDelta: 0
-; EMPTY-NEXT: IsStatement: Yes
-; EMPTY-NEXT: }
-; EMPTY-NEXT: }
-; EMPTY-NEXT: }
-; EMPTY-NEXT: FileChecksums {
-; EMPTY-NEXT: Checksum {
-; EMPTY-NEXT: FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-; EMPTY-NEXT: Kind: MD5 (0x1)
-; EMPTY-NEXT: Checksum (
-; EMPTY-NEXT: 0000: A0A5BD0D 3ECD93FC 29D19DE8 26FBF4BC |....>...)...&...|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Name: * Linker *
-; EMPTY-NEXT: Debug Stream Index: 14
-; EMPTY-NEXT: Object File Name:
-; EMPTY-NEXT: Num Files: 0
-; EMPTY-NEXT: Source File Name Idx: 0
-; EMPTY-NEXT: Pdb File Name Idx: 1
-; EMPTY-NEXT: Line Info Byte Size: 0
-; EMPTY-NEXT: C13 Line Info Byte Size: 0
-; EMPTY-NEXT: Symbol Byte Size: 516
-; EMPTY-NEXT: Type Server Index: 0
-; EMPTY-NEXT: Has EC Info: No
-; EMPTY-NEXT: 0 Contributing Source Files [
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Symbols [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: ObjectName {
-; EMPTY-NEXT: Signature: 0x0
-; EMPTY-NEXT: ObjectName: * Linker *
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 2A204C69 6E6B6572 202A0000 |....* Linker *..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: CompilerFlags3 {
-; EMPTY-NEXT: Language: Link (0x7)
-; EMPTY-NEXT: Flags [ (0x0)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Machine: Intel80386 (0x3)
-; EMPTY-NEXT: FrontendVersion: 0.0.0.0
-; EMPTY-NEXT: BackendVersion: 12.0.31101.0
-; EMPTY-NEXT: VersionName: Microsoft (R) LINK
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 07000000 03000000 00000000 00000C00 |................|
-; EMPTY-NEXT: 0010: 00007D79 00004D69 63726F73 6F667420 |..}y..Microsoft |
-; EMPTY-NEXT: 0020: 28522920 4C494E4B 00000000 |(R) LINK....|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: EnvBlock {
-; EMPTY-NEXT: Entries [
-; EMPTY-NEXT: cwd
-; EMPTY-NEXT: d:\src\llvm\test\DebugInfo\PDB\Inputs
-; EMPTY-NEXT: exe
-; EMPTY-NEXT: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\link.exe
-; EMPTY-NEXT: pdb
-; EMPTY-NEXT: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.pdb
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00637764 00643A5C 7372635C 6C6C766D |.cwd.d:\src\llvm|
-; EMPTY-NEXT: 0010: 5C746573 745C4465 62756749 6E666F5C |\test\DebugInfo\|
-; EMPTY-NEXT: 0020: 5044425C 496E7075 74730065 78650043 |PDB\Inputs.exe.C|
-; EMPTY-NEXT: 0030: 3A5C5072 6F677261 6D204669 6C657320 |:\Program Files |
-; EMPTY-NEXT: 0040: 28783836 295C4D69 63726F73 6F667420 |(x86)\Microsoft |
-; EMPTY-NEXT: 0050: 56697375 616C2053 74756469 6F203132 |Visual Studio 12|
-; EMPTY-NEXT: 0060: 2E305C56 435C4249 4E5C6C69 6E6B2E65 |.0\VC\BIN\link.e|
-; EMPTY-NEXT: 0070: 78650070 64620064 3A5C7372 635C6C6C |xe.pdb.d:\src\ll|
-; EMPTY-NEXT: 0080: 766D5C74 6573745C 44656275 67496E66 |vm\test\DebugInf|
-; EMPTY-NEXT: 0090: 6F5C5044 425C496E 70757473 5C656D70 |o\PDB\Inputs\emp|
-; EMPTY-NEXT: 00A0: 74792E70 64620000 |ty.pdb..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Trampoline {
-; EMPTY-NEXT: Type: TrampIncremental (0x0)
-; EMPTY-NEXT: Size: 5
-; EMPTY-NEXT: ThunkOff: 5
-; EMPTY-NEXT: TargetOff: 16
-; EMPTY-NEXT: ThunkSection: 1
-; EMPTY-NEXT: TargetSection: 1
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000500 05000000 10000000 01000100 |................|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Section {
-; EMPTY-NEXT: SectionNumber: 1
-; EMPTY-NEXT: Alignment: 12
-; EMPTY-NEXT: Rva: 4096
-; EMPTY-NEXT: Length: 4122
-; EMPTY-NEXT: Characteristics [ (0x60000020)
-; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20)
-; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Name: .text
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 01000C00 00100000 1A100000 20000060 |............ ..`|
-; EMPTY-NEXT: 0010: 2E746578 74000000 |.text...|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: COFF Group {
-; EMPTY-NEXT: Size: 4122
-; EMPTY-NEXT: Characteristics [ (0x60000020)
-; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20)
-; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: Segment: 1
-; EMPTY-NEXT: Name: .text$mn
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 1A100000 20000060 00000000 01002E74 |.... ..`.......t|
-; EMPTY-NEXT: 0010: 65787424 6D6E0000 |ext$mn..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Section {
-; EMPTY-NEXT: SectionNumber: 2
-; EMPTY-NEXT: Alignment: 12
-; EMPTY-NEXT: Rva: 12288
-; EMPTY-NEXT: Length: 690
-; EMPTY-NEXT: Characteristics [ (0x40000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Name: .rdata
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 02000C00 00300000 B2020000 40000040 |.....0......@..@|
-; EMPTY-NEXT: 0010: 2E726461 74610000 |.rdata..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: COFF Group {
-; EMPTY-NEXT: Size: 323
-; EMPTY-NEXT: Characteristics [ (0x40000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: Segment: 2
-; EMPTY-NEXT: Name: .rdata
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 43010000 40000040 00000000 02002E72 |C...@..@.......r|
-; EMPTY-NEXT: 0010: 64617461 00000000 |data....|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: COFF Group {
-; EMPTY-NEXT: Size: 0
-; EMPTY-NEXT: Characteristics [ (0x40000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Offset: 323
-; EMPTY-NEXT: Segment: 2
-; EMPTY-NEXT: Name: .edata
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 40000040 43010000 02002E65 |....@..@C......e|
-; EMPTY-NEXT: 0010: 64617461 00000000 |data....|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: COFF Group {
-; EMPTY-NEXT: Size: 366
-; EMPTY-NEXT: Characteristics [ (0x40000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Offset: 324
-; EMPTY-NEXT: Segment: 2
-; EMPTY-NEXT: Name: .rdata$debug
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 6E010000 40000040 44010000 02002E72 |n...@..@D......r|
-; EMPTY-NEXT: 0010: 64617461 24646562 75670000 |data$debug..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Section {
-; EMPTY-NEXT: SectionNumber: 3
-; EMPTY-NEXT: Alignment: 12
-; EMPTY-NEXT: Rva: 16384
-; EMPTY-NEXT: Length: 4
-; EMPTY-NEXT: Characteristics [ (0xC0000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Name: .data
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 03000C00 00400000 04000000 400000C0 |.....@......@...|
-; EMPTY-NEXT: 0010: 2E646174 61000000 |.data...|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: COFF Group {
-; EMPTY-NEXT: Size: 4
-; EMPTY-NEXT: Characteristics [ (0xC0000080)
-; EMPTY-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: Segment: 3
-; EMPTY-NEXT: Name: .bss
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 04000000 800000C0 00000000 03002E62 |...............b|
-; EMPTY-NEXT: 0010: 73730000 |ss..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Section {
-; EMPTY-NEXT: SectionNumber: 4
-; EMPTY-NEXT: Alignment: 12
-; EMPTY-NEXT: Rva: 20480
-; EMPTY-NEXT: Length: 8
-; EMPTY-NEXT: Characteristics [ (0x42000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Name: .reloc
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 04000C00 00500000 08000000 40000042 |.....P......@..B|
-; EMPTY-NEXT: 0010: 2E72656C 6F630000 |.reloc..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Subsections [
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Section Contributions [
-; EMPTY-NEXT: Contribution {
-; EMPTY-NEXT: ISect: 1
-; EMPTY-NEXT: Off: 0
-; EMPTY-NEXT: Size: 10
-; EMPTY-NEXT: Characteristics [ (0x60000020)
-; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20)
-; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Module {
-; EMPTY-NEXT: Index: 1
-; EMPTY-NEXT: Name: * Linker *
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Data CRC: 0
-; EMPTY-NEXT: Reloc CRC: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Contribution {
-; EMPTY-NEXT: ISect: 1
-; EMPTY-NEXT: Off: 16
-; EMPTY-NEXT: Size: 10
-; EMPTY-NEXT: Characteristics [ (0x60500020)
-; EMPTY-NEXT: IMAGE_SCN_ALIGN_16BYTES (0x500000)
-; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20)
-; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Module {
-; EMPTY-NEXT: Index: 0
-; EMPTY-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Data CRC: 3617027124
-; EMPTY-NEXT: Reloc CRC: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Contribution {
-; EMPTY-NEXT: ISect: 2
-; EMPTY-NEXT: Off: 0
-; EMPTY-NEXT: Size: 56
-; EMPTY-NEXT: Characteristics [ (0x40000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Module {
-; EMPTY-NEXT: Index: 1
-; EMPTY-NEXT: Name: * Linker *
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Data CRC: 0
-; EMPTY-NEXT: Reloc CRC: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Contribution {
-; EMPTY-NEXT: ISect: 2
-; EMPTY-NEXT: Off: 324
-; EMPTY-NEXT: Size: 72
-; EMPTY-NEXT: Characteristics [ (0x40300040)
-; EMPTY-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Module {
-; EMPTY-NEXT: Index: 1
-; EMPTY-NEXT: Name: * Linker *
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Data CRC: 0
-; EMPTY-NEXT: Reloc CRC: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Contribution {
-; EMPTY-NEXT: ISect: 2
-; EMPTY-NEXT: Off: 396
-; EMPTY-NEXT: Size: 20
-; EMPTY-NEXT: Characteristics [ (0x40300040)
-; EMPTY-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Module {
-; EMPTY-NEXT: Index: 1
-; EMPTY-NEXT: Name: * Linker *
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Data CRC: 0
-; EMPTY-NEXT: Reloc CRC: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Contribution {
-; EMPTY-NEXT: ISect: 3
-; EMPTY-NEXT: Off: 0
-; EMPTY-NEXT: Size: 4
-; EMPTY-NEXT: Characteristics [ (0xC0300080)
-; EMPTY-NEXT: IMAGE_SCN_ALIGN_4BYTES (0x300000)
-; EMPTY-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Module {
-; EMPTY-NEXT: Index: 0
-; EMPTY-NEXT: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Data CRC: 0
-; EMPTY-NEXT: Reloc CRC: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Section Map [
-; EMPTY-NEXT: Entry {
-; EMPTY-NEXT: Flags [ (0x10D)
-; EMPTY-NEXT: AddressIs32Bit (0x8)
-; EMPTY-NEXT: Execute (0x4)
-; EMPTY-NEXT: IsSelector (0x100)
-; EMPTY-NEXT: Read (0x1)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Ovl: 0
-; EMPTY-NEXT: Group: 0
-; EMPTY-NEXT: Frame: 1
-; EMPTY-NEXT: SecName: 65535
-; EMPTY-NEXT: ClassName: 65535
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: SecByteLength: 4122
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Entry {
-; EMPTY-NEXT: Flags [ (0x109)
-; EMPTY-NEXT: AddressIs32Bit (0x8)
-; EMPTY-NEXT: IsSelector (0x100)
-; EMPTY-NEXT: Read (0x1)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Ovl: 0
-; EMPTY-NEXT: Group: 0
-; EMPTY-NEXT: Frame: 2
-; EMPTY-NEXT: SecName: 65535
-; EMPTY-NEXT: ClassName: 65535
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: SecByteLength: 690
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Entry {
-; EMPTY-NEXT: Flags [ (0x10B)
-; EMPTY-NEXT: AddressIs32Bit (0x8)
-; EMPTY-NEXT: IsSelector (0x100)
-; EMPTY-NEXT: Read (0x1)
-; EMPTY-NEXT: Write (0x2)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Ovl: 0
-; EMPTY-NEXT: Group: 0
-; EMPTY-NEXT: Frame: 3
-; EMPTY-NEXT: SecName: 65535
-; EMPTY-NEXT: ClassName: 65535
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: SecByteLength: 4
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Entry {
-; EMPTY-NEXT: Flags [ (0x109)
-; EMPTY-NEXT: AddressIs32Bit (0x8)
-; EMPTY-NEXT: IsSelector (0x100)
-; EMPTY-NEXT: Read (0x1)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Ovl: 0
-; EMPTY-NEXT: Group: 0
-; EMPTY-NEXT: Frame: 4
-; EMPTY-NEXT: SecName: 65535
-; EMPTY-NEXT: ClassName: 65535
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: SecByteLength: 8
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Entry {
-; EMPTY-NEXT: Flags [ (0x208)
-; EMPTY-NEXT: AddressIs32Bit (0x8)
-; EMPTY-NEXT: IsAbsoluteAddress (0x200)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Ovl: 0
-; EMPTY-NEXT: Group: 0
-; EMPTY-NEXT: Frame: 0
-; EMPTY-NEXT: SecName: 65535
-; EMPTY-NEXT: ClassName: 65535
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: SecByteLength: 4294967295
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: Globals Stream {
-; EMPTY-NEXT: Stream number: 6
-; EMPTY-NEXT: Number of buckets: 2
-; EMPTY-NEXT: Hash Buckets: [0, 12]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Publics Stream {
-; EMPTY-NEXT: Stream number: 7
-; EMPTY-NEXT: SymHash: 556
-; EMPTY-NEXT: AddrMap: 8
-; EMPTY-NEXT: Number of buckets: 2
-; EMPTY-NEXT: Hash Buckets: [0, 12]
-; EMPTY-NEXT: Address Map: [36, 0]
-; EMPTY-NEXT: Thunk Map: [4112]
-; EMPTY-NEXT: Section Offsets: [4096, 1]
-; EMPTY-NEXT: Symbols [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: PublicSym {
-; EMPTY-NEXT: Type: 0
-; EMPTY-NEXT: Seg: 3
-; EMPTY-NEXT: Off: 0
-; EMPTY-NEXT: Name: ?__purecall@@3PAXA
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 00000000 03003F5F 5F707572 |..........?__pur|
-; EMPTY-NEXT: 0010: 6563616C 6C404033 50415841 00000000 |ecall@@3PAXA....|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: PublicSym {
-; EMPTY-NEXT: Type: 2
-; EMPTY-NEXT: Seg: 1
-; EMPTY-NEXT: Off: 16
-; EMPTY-NEXT: Name: _main
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 02000000 10000000 01005F6D 61696E00 |.........._main.|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: ProcRef {
-; EMPTY-NEXT: SumName: 0
-; EMPTY-NEXT: SymOffset: 120
-; EMPTY-NEXT: Mod: 1
-; EMPTY-NEXT: Name: main
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 00000000 78000000 01006D61 696E0000 |....x.....main..|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: DataSym {
-; EMPTY-NEXT: Kind: S_GDATA32 (0x110D)
-; EMPTY-NEXT: Type: void* (0x403)
-; EMPTY-NEXT: DisplayName: __purecall
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Bytes (
-; EMPTY-NEXT: 0000: 03040000 00000000 03005F5F 70757265 |..........__pure|
-; EMPTY-NEXT: 0010: 63616C6C 00000000 |call....|
-; EMPTY-NEXT: )
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: Section Headers [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Name: .text
-; EMPTY-NEXT: Virtual Size: 4122
-; EMPTY-NEXT: Virtual Address: 4096
-; EMPTY-NEXT: Size of Raw Data: 4608
-; EMPTY-NEXT: File Pointer to Raw Data: 1024
-; EMPTY-NEXT: File Pointer to Relocations: 0
-; EMPTY-NEXT: File Pointer to Linenumbers: 0
-; EMPTY-NEXT: Number of Relocations: 0
-; EMPTY-NEXT: Number of Linenumbers: 0
-; EMPTY-NEXT: Characteristics [ (0x60000020)
-; EMPTY-NEXT: IMAGE_SCN_CNT_CODE (0x20)
-; EMPTY-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Name: .rdata
-; EMPTY-NEXT: Virtual Size: 690
-; EMPTY-NEXT: Virtual Address: 12288
-; EMPTY-NEXT: Size of Raw Data: 1024
-; EMPTY-NEXT: File Pointer to Raw Data: 5632
-; EMPTY-NEXT: File Pointer to Relocations: 0
-; EMPTY-NEXT: File Pointer to Linenumbers: 0
-; EMPTY-NEXT: Number of Relocations: 0
-; EMPTY-NEXT: Number of Linenumbers: 0
-; EMPTY-NEXT: Characteristics [ (0x40000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Name: .data
-; EMPTY-NEXT: Virtual Size: 4
-; EMPTY-NEXT: Virtual Address: 16384
-; EMPTY-NEXT: Size of Raw Data: 0
-; EMPTY-NEXT: File Pointer to Raw Data: 0
-; EMPTY-NEXT: File Pointer to Relocations: 0
-; EMPTY-NEXT: File Pointer to Linenumbers: 0
-; EMPTY-NEXT: Number of Relocations: 0
-; EMPTY-NEXT: Number of Linenumbers: 0
-; EMPTY-NEXT: Characteristics [ (0xC0000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Name: .reloc
-; EMPTY-NEXT: Virtual Size: 8
-; EMPTY-NEXT: Virtual Address: 20480
-; EMPTY-NEXT: Size of Raw Data: 512
-; EMPTY-NEXT: File Pointer to Raw Data: 6656
-; EMPTY-NEXT: File Pointer to Relocations: 0
-; EMPTY-NEXT: File Pointer to Linenumbers: 0
-; EMPTY-NEXT: Number of Relocations: 0
-; EMPTY-NEXT: Number of Linenumbers: 0
-; EMPTY-NEXT: Characteristics [ (0x42000040)
-; EMPTY-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; EMPTY-NEXT: IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
-; EMPTY-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-; EMPTY-NEXT: ]
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
-; EMPTY: New FPO [
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Offset: 4112
-; EMPTY-NEXT: Size: 10
-; EMPTY-NEXT: Number of locals: 0
-; EMPTY-NEXT: Number of params: 0
-; EMPTY-NEXT: Size of Prolog: 0
-; EMPTY-NEXT: Number of Saved Registers: 0
-; EMPTY-NEXT: Has SEH: No
-; EMPTY-NEXT: Use BP: No
-; EMPTY-NEXT: Frame Pointer: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: {
-; EMPTY-NEXT: Offset: 0
-; EMPTY-NEXT: Size: 134
-; EMPTY-NEXT: Number of locals: 3
-; EMPTY-NEXT: Number of params: 4
-; EMPTY-NEXT: Size of Prolog: 0
-; EMPTY-NEXT: Number of Saved Registers: 0
-; EMPTY-NEXT: Has SEH: No
-; EMPTY-NEXT: Use BP: No
-; EMPTY-NEXT: Frame Pointer: 0
-; EMPTY-NEXT: }
-; EMPTY-NEXT: ]
+ALL: Summary
+ALL-NEXT: ============================================================
+ALL-NEXT: Block Size: 4096
+ALL-NEXT: Number of blocks: 25
+ALL-NEXT: Number of streams: 17
+ALL-NEXT: Signature: 1424295906
+ALL-NEXT: Age: 1
+ALL-NEXT: GUID: {0B355641-86A0-A249-896F-9988FAE52FF0}
+ALL-NEXT: Features: 0x1
+ALL-NEXT: Has Debug Info: true
+ALL-NEXT: Has Types: true
+ALL-NEXT: Has IDs: true
+ALL-NEXT: Has Globals: true
+ALL-NEXT: Has Publics: true
+ALL-NEXT: Is incrementally linked: true
+ALL-NEXT: Has conflicting types: false
+ALL-NEXT: Is stripped: false
+ALL: Streams
+ALL-NEXT: ============================================================
+ALL-NEXT: Stream 0: [Old MSF Directory] (40 bytes)
+ALL-NEXT: Stream 1: [PDB Stream] (118 bytes)
+ALL-NEXT: Stream 2: [TPI Stream] (5392 bytes)
+ALL-NEXT: Stream 3: [DBI Stream] (739 bytes)
+ALL-NEXT: Stream 4: [IPI Stream] (784 bytes)
+ALL-NEXT: Stream 5: [Named Stream "/LinkInfo"] (0 bytes)
+ALL-NEXT: Stream 6: [Global Symbol Hash] (556 bytes)
+ALL-NEXT: Stream 7: [Public Symbol Hash] (604 bytes)
+ALL-NEXT: Stream 8: [Public Symbol Records] (104 bytes)
+ALL-NEXT: Stream 9: [Named Stream "/src/headerblock"] (0 bytes)
+ALL-NEXT: Stream 10: [Section Header Data] (160 bytes)
+ALL-NEXT: Stream 11: [New FPO Data] (32 bytes)
+ALL-NEXT: Stream 12: [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"] (308 bytes)
+ALL-NEXT: Stream 13: [Named Stream "/names"] (239 bytes)
+ALL-NEXT: Stream 14: [Module "* Linker *"] (520 bytes)
+ALL-NEXT: Stream 15: [TPI Hash] (308 bytes)
+ALL-NEXT: Stream 16: [IPI Hash] (68 bytes)
+ALL: String Table
+ALL-NEXT: ============================================================
+ALL-NEXT: ID | String
+ALL-NEXT: 1 | 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)'
+ALL-NEXT: 86 | 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
+ALL-NEXT: 134 | '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = '
+ALL: Modules
+ALL-NEXT: ============================================================
+ALL-NEXT: Mod 0000 | Name: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT: Obj: `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT: debug stream: 12, # files: 1, has ec info: false
+ALL-NEXT: Mod 0001 | Name: `* Linker *`:
+ALL-NEXT: Obj: ``:
+ALL-NEXT: debug stream: 14, # files: 0, has ec info: false
+ALL: Files
+ALL-NEXT: ============================================================
+ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT: - (MD5: A0A5BD0D3ECD93FC29D19DE826FBF4BC) d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+ALL-NEXT: Mod 0001 | `* Linker *`:
+ALL: Lines
+ALL-NEXT: ============================================================
+ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp (MD5: A0A5BD0D3ECD93FC29D19DE826FBF4BC)
+ALL-NEXT: 0001:00000010-0000001A, line/addr entries = 3
+ALL-NEXT: 5 00000010 6 00000013 7 00000018
+ALL: Mod 0001 | `* Linker *`:
+ALL: Inlinee Lines
+ALL-NEXT: ============================================================
+ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT: Mod 0001 | `* Linker *`:
+ALL: Types (TPI Stream)
+ALL-NEXT: ============================================================
+ALL-NEXT: Showing 75 records
+ALL-NEXT: 0x1000 | LF_ARGLIST [size = 8, hash = 205956]
+ALL-NEXT: 0x1001 | LF_PROCEDURE [size = 16, hash = 163561]
+ALL-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1000
+ALL-NEXT: calling conv = cdecl, options = None
+ALL-NEXT: 0x1002 | LF_FIELDLIST [size = 76, hash = 59811]
+ALL-NEXT: - LF_ENUMERATE [apartment = 1]
+ALL-NEXT: - LF_ENUMERATE [single = 2]
+ALL-NEXT: - LF_ENUMERATE [free = 3]
+ALL-NEXT: - LF_ENUMERATE [neutral = 4]
+ALL-NEXT: - LF_ENUMERATE [both = 5]
+ALL-NEXT: 0x1003 | LF_ENUM [size = 120, hash = 208239]
+ALL-NEXT: name: `__vc_attributes::threadingAttribute::threading_e`
+ALL-NEXT: unique name: `.?AW4threading_e@threadingAttribute@__vc_attributes@@`
+ALL-NEXT: field list: 0x1002, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x1004 | LF_STRUCTURE [size = 100, hash = 16377]
+ALL-NEXT: class name: `__vc_attributes::threadingAttribute`
+ALL-NEXT: unique name: `.?AUthreadingAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+ALL-NEXT: options: forward ref | has unique name
+ALL-NEXT: 0x1005 | LF_POINTER [size = 12, hash = 247078]
+ALL-NEXT: referent = 0x1004, mode = pointer, opts = const, kind = ptr32
+ALL-NEXT: 0x1006 | LF_ARGLIST [size = 12, hash = 194342]
+ALL-NEXT: 0x1003: `__vc_attributes::threadingAttribute::threading_e`
+ALL-NEXT: 0x1007 | LF_MFUNCTION [size = 28, hash = 254156]
+ALL-NEXT: return type = 1, # args = 0x1006, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x1004, this type = 0x1005, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1008 | LF_MFUNCTION [size = 28, hash = 194536]
+ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x1004, this type = 0x1005, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1009 | LF_METHODLIST [size = 20, hash = 167492]
+ALL-NEXT: - Method [type = 0x1007, vftable offset = -1, attrs = public]
+ALL-NEXT: - Method [type = 0x1008, vftable offset = -1, attrs = public]
+ALL-NEXT: 0x100A | LF_FIELDLIST [size = 68, hash = 185421]
+ALL-NEXT: - LF_NESTTYPE [name = `threading_e`, parent = 0x1003]
+ALL-NEXT: - LF_METHOD [name = `threadingAttribute`, # overloads = 2, overload list = 0x1009]
+ALL-NEXT: - LF_MEMBER [name = `value`, Type = 0x1003, offset = 0, attrs = public]
+ALL-NEXT: 0x100B | LF_STRUCTURE [size = 100, hash = 119540]
+ALL-NEXT: class name: `__vc_attributes::threadingAttribute`
+ALL-NEXT: unique name: `.?AUthreadingAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: 0x100A
+ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name
+ALL-NEXT: 0x100C | LF_FIELDLIST [size = 48, hash = 261871]
+ALL-NEXT: - LF_ENUMERATE [native = 0]
+ALL-NEXT: - LF_ENUMERATE [com = 1]
+ALL-NEXT: - LF_ENUMERATE [managed = 2]
+ALL-NEXT: 0x100D | LF_ENUM [size = 120, hash = 198119]
+ALL-NEXT: name: `__vc_attributes::event_receiverAttribute::type_e`
+ALL-NEXT: unique name: `.?AW4type_e@event_receiverAttribute@__vc_attributes@@`
+ALL-NEXT: field list: 0x100C, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x100E | LF_STRUCTURE [size = 112, hash = 48056]
+ALL-NEXT: class name: `__vc_attributes::event_receiverAttribute`
+ALL-NEXT: unique name: `.?AUevent_receiverAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+ALL-NEXT: options: forward ref | has unique name
+ALL-NEXT: 0x100F | LF_POINTER [size = 12, hash = 251486]
+ALL-NEXT: referent = 0x100E, mode = pointer, opts = const, kind = ptr32
+ALL-NEXT: 0x1010 | LF_ARGLIST [size = 16, hash = 134580]
+ALL-NEXT: 0x100D: `__vc_attributes::event_receiverAttribute::type_e`
+ALL-NEXT: 0x0030 (bool): `bool`
+ALL-NEXT: 0x1011 | LF_MFUNCTION [size = 28, hash = 148190]
+ALL-NEXT: return type = 2, # args = 0x1010, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x100E, this type = 0x100F, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1012 | LF_ARGLIST [size = 12, hash = 113636]
+ALL-NEXT: 0x100D: `__vc_attributes::event_receiverAttribute::type_e`
+ALL-NEXT: 0x1013 | LF_MFUNCTION [size = 28, hash = 53336]
+ALL-NEXT: return type = 1, # args = 0x1012, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x100E, this type = 0x100F, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1014 | LF_MFUNCTION [size = 28, hash = 55779]
+ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x100E, this type = 0x100F, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1015 | LF_METHODLIST [size = 28, hash = 220695]
+ALL-NEXT: - Method [type = 0x1011, vftable offset = -1, attrs = public]
+ALL-NEXT: - Method [type = 0x1013, vftable offset = -1, attrs = public]
+ALL-NEXT: - Method [type = 0x1014, vftable offset = -1, attrs = public]
+ALL-NEXT: 0x1016 | LF_FIELDLIST [size = 96, hash = 198114]
+ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x100D]
+ALL-NEXT: - LF_METHOD [name = `event_receiverAttribute`, # overloads = 3, overload list = 0x1015]
+ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x100D, offset = 0, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `layout_dependent`, Type = 0x0030 (bool), offset = 4, attrs = public]
+ALL-NEXT: 0x1017 | LF_STRUCTURE [size = 112, hash = 148734]
+ALL-NEXT: class name: `__vc_attributes::event_receiverAttribute`
+ALL-NEXT: unique name: `.?AUevent_receiverAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1016
+ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name
+ALL-NEXT: 0x1018 | LF_FIELDLIST [size = 48, hash = 81128]
+ALL-NEXT: - LF_ENUMERATE [never = 0]
+ALL-NEXT: - LF_ENUMERATE [allowed = 1]
+ALL-NEXT: - LF_ENUMERATE [always = 2]
+ALL-NEXT: 0x1019 | LF_ENUM [size = 116, hash = 60158]
+ALL-NEXT: name: `__vc_attributes::aggregatableAttribute::type_e`
+ALL-NEXT: unique name: `.?AW4type_e@aggregatableAttribute@__vc_attributes@@`
+ALL-NEXT: field list: 0x1018, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x101A | LF_STRUCTURE [size = 108, hash = 217249]
+ALL-NEXT: class name: `__vc_attributes::aggregatableAttribute`
+ALL-NEXT: unique name: `.?AUaggregatableAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+ALL-NEXT: options: forward ref | has unique name
+ALL-NEXT: 0x101B | LF_POINTER [size = 12, hash = 174209]
+ALL-NEXT: referent = 0x101A, mode = pointer, opts = const, kind = ptr32
+ALL-NEXT: 0x101C | LF_ARGLIST [size = 12, hash = 159978]
+ALL-NEXT: 0x1019: `__vc_attributes::aggregatableAttribute::type_e`
+ALL-NEXT: 0x101D | LF_MFUNCTION [size = 28, hash = 249504]
+ALL-NEXT: return type = 1, # args = 0x101C, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x101A, this type = 0x101B, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x101E | LF_MFUNCTION [size = 28, hash = 141941]
+ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x101A, this type = 0x101B, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x101F | LF_METHODLIST [size = 20, hash = 238785]
+ALL-NEXT: - Method [type = 0x101D, vftable offset = -1, attrs = public]
+ALL-NEXT: - Method [type = 0x101E, vftable offset = -1, attrs = public]
+ALL-NEXT: 0x1020 | LF_FIELDLIST [size = 68, hash = 6214]
+ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x1019]
+ALL-NEXT: - LF_METHOD [name = `aggregatableAttribute`, # overloads = 2, overload list = 0x101F]
+ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x1019, offset = 0, attrs = public]
+ALL-NEXT: 0x1021 | LF_STRUCTURE [size = 108, hash = 94935]
+ALL-NEXT: class name: `__vc_attributes::aggregatableAttribute`
+ALL-NEXT: unique name: `.?AUaggregatableAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1020
+ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name
+ALL-NEXT: 0x1022 | LF_ENUM [size = 116, hash = 151449]
+ALL-NEXT: name: `__vc_attributes::event_sourceAttribute::type_e`
+ALL-NEXT: unique name: `.?AW4type_e@event_sourceAttribute@__vc_attributes@@`
+ALL-NEXT: field list: 0x100C, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x1023 | LF_FIELDLIST [size = 28, hash = 135589]
+ALL-NEXT: - LF_ENUMERATE [speed = 0]
+ALL-NEXT: - LF_ENUMERATE [size = 1]
+ALL-NEXT: 0x1024 | LF_ENUM [size = 124, hash = 73373]
+ALL-NEXT: name: `__vc_attributes::event_sourceAttribute::optimize_e`
+ALL-NEXT: unique name: `.?AW4optimize_e@event_sourceAttribute@__vc_attributes@@`
+ALL-NEXT: field list: 0x1023, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x1025 | LF_STRUCTURE [size = 108, hash = 96512]
+ALL-NEXT: class name: `__vc_attributes::event_sourceAttribute`
+ALL-NEXT: unique name: `.?AUevent_sourceAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+ALL-NEXT: options: forward ref | has unique name
+ALL-NEXT: 0x1026 | LF_POINTER [size = 12, hash = 254299]
+ALL-NEXT: referent = 0x1025, mode = pointer, opts = const, kind = ptr32
+ALL-NEXT: 0x1027 | LF_ARGLIST [size = 12, hash = 17744]
+ALL-NEXT: 0x1022: `__vc_attributes::event_sourceAttribute::type_e`
+ALL-NEXT: 0x1028 | LF_MFUNCTION [size = 28, hash = 239514]
+ALL-NEXT: return type = 1, # args = 0x1027, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x1025, this type = 0x1026, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1029 | LF_MFUNCTION [size = 28, hash = 173189]
+ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x1025, this type = 0x1026, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x102A | LF_METHODLIST [size = 20, hash = 130544]
+ALL-NEXT: - Method [type = 0x1028, vftable offset = -1, attrs = public]
+ALL-NEXT: - Method [type = 0x1029, vftable offset = -1, attrs = public]
+ALL-NEXT: 0x102B | LF_FIELDLIST [size = 128, hash = 204437]
+ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x1022]
+ALL-NEXT: - LF_NESTTYPE [name = `optimize_e`, parent = 0x1024]
+ALL-NEXT: - LF_METHOD [name = `event_sourceAttribute`, # overloads = 2, overload list = 0x102A]
+ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x1022, offset = 0, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `optimize`, Type = 0x1024, offset = 4, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `decorate`, Type = 0x0030 (bool), offset = 8, attrs = public]
+ALL-NEXT: 0x102C | LF_STRUCTURE [size = 108, hash = 238560]
+ALL-NEXT: class name: `__vc_attributes::event_sourceAttribute`
+ALL-NEXT: unique name: `.?AUevent_sourceAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: 0x102B
+ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name
+ALL-NEXT: 0x102D | LF_FIELDLIST [size = 92, hash = 144673]
+ALL-NEXT: - LF_ENUMERATE [dll = 1]
+ALL-NEXT: - LF_ENUMERATE [exe = 2]
+ALL-NEXT: - LF_ENUMERATE [service = 3]
+ALL-NEXT: - LF_ENUMERATE [unspecified = 4]
+ALL-NEXT: - LF_ENUMERATE [EXE = 2]
+ALL-NEXT: - LF_ENUMERATE [SERVICE = 3]
+ALL-NEXT: 0x102E | LF_ENUM [size = 104, hash = 115151]
+ALL-NEXT: name: `__vc_attributes::moduleAttribute::type_e`
+ALL-NEXT: unique name: `.?AW4type_e@moduleAttribute@__vc_attributes@@`
+ALL-NEXT: field list: 0x102D, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x102F | LF_STRUCTURE [size = 96, hash = 197306]
+ALL-NEXT: class name: `__vc_attributes::moduleAttribute`
+ALL-NEXT: unique name: `.?AUmoduleAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+ALL-NEXT: options: forward ref | has unique name
+ALL-NEXT: 0x1030 | LF_POINTER [size = 12, hash = 256035]
+ALL-NEXT: referent = 0x102F, mode = pointer, opts = const, kind = ptr32
+ALL-NEXT: 0x1031 | LF_MODIFIER [size = 12, hash = 101096]
+ALL-NEXT: referent = 0x0070 (char), modifiers = const
+ALL-NEXT: 0x1032 | LF_POINTER [size = 12, hash = 231280]
+ALL-NEXT: referent = 0x1031, mode = pointer, opts = None, kind = ptr32
+ALL-NEXT: 0x1033 | LF_ARGLIST [size = 68, hash = 52156]
+ALL-NEXT: 0x102E: `__vc_attributes::moduleAttribute::type_e`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x0074 (int): `int`
+ALL-NEXT: 0x0030 (bool): `bool`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x0074 (int): `int`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x0074 (int): `int`
+ALL-NEXT: 0x0030 (bool): `bool`
+ALL-NEXT: 0x0030 (bool): `bool`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x1032: `const char*`
+ALL-NEXT: 0x1034 | LF_MFUNCTION [size = 28, hash = 48854]
+ALL-NEXT: return type = 15, # args = 0x1033, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x102F, this type = 0x1030, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1035 | LF_ARGLIST [size = 12, hash = 170035]
+ALL-NEXT: 0x102E: `__vc_attributes::moduleAttribute::type_e`
+ALL-NEXT: 0x1036 | LF_MFUNCTION [size = 28, hash = 177041]
+ALL-NEXT: return type = 1, # args = 0x1035, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x102F, this type = 0x1030, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1037 | LF_MFUNCTION [size = 28, hash = 102745]
+ALL-NEXT: return type = 0, # args = 0x1000, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x102F, this type = 0x1030, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1038 | LF_METHODLIST [size = 28, hash = 16947]
+ALL-NEXT: - Method [type = 0x1034, vftable offset = -1, attrs = public]
+ALL-NEXT: - Method [type = 0x1036, vftable offset = -1, attrs = public]
+ALL-NEXT: - Method [type = 0x1037, vftable offset = -1, attrs = public]
+ALL-NEXT: 0x1039 | LF_FIELDLIST [size = 356, hash = 183703]
+ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x102E]
+ALL-NEXT: - LF_METHOD [name = `moduleAttribute`, # overloads = 3, overload list = 0x1038]
+ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x102E, offset = 0, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `name`, Type = 0x1032, offset = 4, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `version`, Type = 0x1032, offset = 8, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `uuid`, Type = 0x1032, offset = 12, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `lcid`, Type = 0x0074 (int), offset = 16, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `control`, Type = 0x0030 (bool), offset = 20, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `helpstring`, Type = 0x1032, offset = 24, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `helpstringcontext`, Type = 0x0074 (int), offset = 28, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `helpstringdll`, Type = 0x1032, offset = 32, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `helpfile`, Type = 0x1032, offset = 36, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `helpcontext`, Type = 0x0074 (int), offset = 40, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `hidden`, Type = 0x0030 (bool), offset = 44, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `restricted`, Type = 0x0030 (bool), offset = 45, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `custom`, Type = 0x1032, offset = 48, attrs = public]
+ALL-NEXT: - LF_MEMBER [name = `resource_name`, Type = 0x1032, offset = 52, attrs = public]
+ALL-NEXT: 0x103A | LF_STRUCTURE [size = 96, hash = 98548]
+ALL-NEXT: class name: `__vc_attributes::moduleAttribute`
+ALL-NEXT: unique name: `.?AUmoduleAttribute@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1039
+ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name
+ALL-NEXT: 0x103B | LF_FIELDLIST [size = 756, hash = 35693]
+ALL-NEXT: - LF_ENUMERATE [eAnyUsage = 0]
+ALL-NEXT: - LF_ENUMERATE [eCoClassUsage = 1]
+ALL-NEXT: - LF_ENUMERATE [eCOMInterfaceUsage = 2]
+ALL-NEXT: - LF_ENUMERATE [eInterfaceUsage = 6]
+ALL-NEXT: - LF_ENUMERATE [eMemberUsage = 8]
+ALL-NEXT: - LF_ENUMERATE [eMethodUsage = 16]
+ALL-NEXT: - LF_ENUMERATE [eInterfaceMethodUsage = 32]
+ALL-NEXT: - LF_ENUMERATE [eInterfaceMemberUsage = 64]
+ALL-NEXT: - LF_ENUMERATE [eCoClassMemberUsage = 128]
+ALL-NEXT: - LF_ENUMERATE [eCoClassMethodUsage = 256]
+ALL-NEXT: - LF_ENUMERATE [eGlobalMethodUsage = 768]
+ALL-NEXT: - LF_ENUMERATE [eGlobalDataUsage = 1024]
+ALL-NEXT: - LF_ENUMERATE [eClassUsage = 2048]
+ALL-NEXT: - LF_ENUMERATE [eInterfaceParameterUsage = 4096]
+ALL-NEXT: - LF_ENUMERATE [eMethodParameterUsage = 12288]
+ALL-NEXT: - LF_ENUMERATE [eIDLModuleUsage = 16384]
+ALL-NEXT: - LF_ENUMERATE [eAnonymousUsage = 32768]
+ALL-NEXT: - LF_ENUMERATE [eTypedefUsage = 65536]
+ALL-NEXT: - LF_ENUMERATE [eUnionUsage = 131072]
+ALL-NEXT: - LF_ENUMERATE [eEnumUsage = 262144]
+ALL-NEXT: - LF_ENUMERATE [eDefineTagUsage = 524288]
+ALL-NEXT: - LF_ENUMERATE [eStructUsage = 1048576]
+ALL-NEXT: - LF_ENUMERATE [eLocalUsage = 2097152]
+ALL-NEXT: - LF_ENUMERATE [ePropertyUsage = 4194304]
+ALL-NEXT: - LF_ENUMERATE [eEventUsage = 8388608]
+ALL-NEXT: - LF_ENUMERATE [eTemplateUsage = 16777216]
+ALL-NEXT: - LF_ENUMERATE [eModuleUsage = 16777216]
+ALL-NEXT: - LF_ENUMERATE [eIllegalUsage = 33554432]
+ALL-NEXT: - LF_ENUMERATE [eAsynchronousUsage = 67108864]
+ALL-NEXT: - LF_ENUMERATE [eAnyIDLUsage = 4161535]
+ALL-NEXT: 0x103C | LF_ENUM [size = 140, hash = 171328]
+ALL-NEXT: name: `__vc_attributes::helper_attributes::usageAttribute::usage_e`
+ALL-NEXT: unique name: `.?AW4usage_e@usageAttribute@helper_attributes@__vc_attributes@@`
+ALL-NEXT: field list: 0x103B, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x103D | LF_STRUCTURE [size = 128, hash = 203640]
+ALL-NEXT: class name: `__vc_attributes::helper_attributes::usageAttribute`
+ALL-NEXT: unique name: `.?AUusageAttribute@helper_attributes@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+ALL-NEXT: options: forward ref | has unique name
+ALL-NEXT: 0x103E | LF_POINTER [size = 12, hash = 139292]
+ALL-NEXT: referent = 0x103D, mode = pointer, opts = const, kind = ptr32
+ALL-NEXT: 0x103F | LF_ARGLIST [size = 12, hash = 49018]
+ALL-NEXT: 0x0075 (unsigned): `unsigned`
+ALL-NEXT: 0x1040 | LF_MFUNCTION [size = 28, hash = 43821]
+ALL-NEXT: return type = 1, # args = 0x103F, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x103D, this type = 0x103E, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1041 | LF_FIELDLIST [size = 60, hash = 202555]
+ALL-NEXT: - LF_NESTTYPE [name = `usage_e`, parent = 0x103C]
+ALL-NEXT: - LF_ONEMETHOD [name = `usageAttribute`]
+ALL-NEXT: type = 0x1040, vftable offset = -1, attrs = public
+ALL-NEXT: - LF_MEMBER [name = `value`, Type = 0x0075 (unsigned), offset = 0, attrs = public]
+ALL-NEXT: 0x1042 | LF_STRUCTURE [size = 128, hash = 165040]
+ALL-NEXT: class name: `__vc_attributes::helper_attributes::usageAttribute`
+ALL-NEXT: unique name: `.?AUusageAttribute@helper_attributes@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1041
+ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name
+ALL-NEXT: 0x1043 | LF_FIELDLIST [size = 68, hash = 215835]
+ALL-NEXT: - LF_ENUMERATE [eBoolean = 0]
+ALL-NEXT: - LF_ENUMERATE [eInteger = 1]
+ALL-NEXT: - LF_ENUMERATE [eFloat = 2]
+ALL-NEXT: - LF_ENUMERATE [eDouble = 3]
+ALL-NEXT: 0x1044 | LF_ENUM [size = 148, hash = 142625]
+ALL-NEXT: name: `__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e`
+ALL-NEXT: unique name: `.?AW4type_e@v1_alttypeAttribute@helper_attributes@__vc_attributes@@`
+ALL-NEXT: field list: 0x1043, underlying type: 0x0074 (int)
+ALL-NEXT: options: has unique name | is nested
+ALL-NEXT: 0x1045 | LF_STRUCTURE [size = 140, hash = 52534]
+ALL-NEXT: class name: `__vc_attributes::helper_attributes::v1_alttypeAttribute`
+ALL-NEXT: unique name: `.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+ALL-NEXT: options: forward ref | has unique name
+ALL-NEXT: 0x1046 | LF_POINTER [size = 12, hash = 44186]
+ALL-NEXT: referent = 0x1045, mode = pointer, opts = const, kind = ptr32
+ALL-NEXT: 0x1047 | LF_ARGLIST [size = 12, hash = 103930]
+ALL-NEXT: 0x1044: `__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e`
+ALL-NEXT: 0x1048 | LF_MFUNCTION [size = 28, hash = 110942]
+ALL-NEXT: return type = 1, # args = 0x1047, param list = 0x0003 (void)
+ALL-NEXT: class type = 0x1045, this type = 0x1046, this adjust = 0
+ALL-NEXT: calling conv = thiscall, options = constructor
+ALL-NEXT: 0x1049 | LF_FIELDLIST [size = 64, hash = 17991]
+ALL-NEXT: - LF_NESTTYPE [name = `type_e`, parent = 0x1044]
+ALL-NEXT: - LF_ONEMETHOD [name = `v1_alttypeAttribute`]
+ALL-NEXT: type = 0x1048, vftable offset = -1, attrs = public
+ALL-NEXT: - LF_MEMBER [name = `type`, Type = 0x1044, offset = 0, attrs = public]
+ALL-NEXT: 0x104A | LF_STRUCTURE [size = 140, hash = 213215]
+ALL-NEXT: class name: `__vc_attributes::helper_attributes::v1_alttypeAttribute`
+ALL-NEXT: unique name: `.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@`
+ALL-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1049
+ALL-NEXT: options: has ctor / dtor | contains nested class | has unique name
+ALL: Type Index Offsets:
+ALL-NEXT: TI: 0x1000, Offset: 0
+ALL: Hash Adjusters:
+ALL: Types (IPI Stream)
+ALL-NEXT: ============================================================
+ALL-NEXT: Showing 15 records
+ALL-NEXT: 0x1000 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7186]
+ALL-NEXT: udt = 0x100B, mod = 1, file = 1, line = 481
+ALL-NEXT: 0x1001 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7198]
+ALL-NEXT: udt = 0x1017, mod = 1, file = 1, line = 194
+ALL-NEXT: 0x1002 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7180]
+ALL-NEXT: udt = 0x1021, mod = 1, file = 1, line = 603
+ALL-NEXT: 0x1003 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7191]
+ALL-NEXT: udt = 0x102C, mod = 1, file = 1, line = 1200
+ALL-NEXT: 0x1004 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7201]
+ALL-NEXT: udt = 0x103A, mod = 1, file = 1, line = 540
+ALL-NEXT: 0x1005 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7241]
+ALL-NEXT: udt = 0x1042, mod = 1, file = 1, line = 108
+ALL-NEXT: 0x1006 | LF_UDT_MOD_SRC_LINE [size = 20, hash = 7249]
+ALL-NEXT: udt = 0x104A, mod = 1, file = 1, line = 96
+ALL-NEXT: 0x1007 | LF_STRING_ID [size = 48, hash = 80727] ID: <no type>, String: d:\src\llvm\test\DebugInfo\PDB\Inputs
+ALL-NEXT: 0x1008 | LF_STRING_ID [size = 76, hash = 154177] ID: <no type>, String: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe
+ALL-NEXT: 0x1009 | LF_STRING_ID [size = 20, hash = 75189] ID: <no type>, String: empty.cpp
+ALL-NEXT: 0x100A | LF_STRING_ID [size = 56, hash = 253662] ID: <no type>, String: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb
+ALL-NEXT: 0x100B | LF_STRING_ID [size = 252, hash = 193467] ID: <no type>, String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows
+ALL-NEXT: 0x100C | LF_SUBSTR_LIST [size = 12, hash = 222705]
+ALL-NEXT: 0x100B: `-Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows`
+ALL-NEXT: 0x100D | LF_STRING_ID [size = 96, hash = 186099] ID: 0x100C, String: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X
+ALL-NEXT: 0x100E | LF_BUILDINFO [size = 28, hash = 257108]
+ALL-NEXT: 0x1007: `d:\src\llvm\test\DebugInfo\PDB\Inputs`
+ALL-NEXT: 0x1008: `C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe`
+ALL-NEXT: 0x1009: `empty.cpp`
+ALL-NEXT: 0x100A: `d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb`
+ALL-NEXT: 0x100D: ` Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X`
+ALL: Type Index Offsets:
+ALL-NEXT: TI: 0x1000, Offset: 0
+ALL: Hash Adjusters:
+ALL: Public Symbols
+ALL-NEXT: ============================================================
+ALL-NEXT: - S_PUB32 [size = 36] `?__purecall@@3PAXA`
+ALL-NEXT: type = <no type>, addr = 0003:0000
+ALL-NEXT: - S_PUB32 [size = 20] `_main`
+ALL-NEXT: type = 0x0002 (<unknown simple type>), addr = 0001:0016
+ALL-NEXT: - S_PROCREF [size = 20] `main`
+ALL-NEXT: module = 1, sum name = 0, offset = 120
+ALL-NEXT: - S_GDATA32 [size = 28] `__purecall`
+ALL-NEXT: type = 0x0403 (void*), addr = 0003:0000
+ALL: Symbols
+ALL-NEXT: ============================================================
+ALL-NEXT: Mod 0000 | `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`:
+ALL-NEXT: - S_OBJNAME [size = 56] sig=0, `d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj`
+ALL-NEXT: - S_COMPILE3 [size = 60]
+ALL-NEXT: machine = intel pentium 3, Ver = Microsoft (R) Optimizing Compiler, language = c++
+ALL-NEXT: frontend = 18.0.31101.0, backend = 18.0.31101.0
+ALL-NEXT: flags = security checks
+ALL-NEXT: - S_GPROC32 [size = 44] `main`
+ALL-NEXT: parent = 0, addr = 0001:0016, code size = 10, end = 196
+ALL-NEXT: debug start = 3, debug end = 8, flags = has fp
+ALL-NEXT: - S_FRAMEPROC [size = 32]
+ALL-NEXT: size = 0, padding size = 0, offset to padding = 0
+ALL-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000
+ALL-NEXT: flags = has async eh | opt speed
+ALL-NEXT: - S_END [size = 4]
+ALL-NEXT: - S_BUILDINFO [size = 8] BuildId = `4110`
+ALL-NEXT: Mod 0001 | `* Linker *`:
+ALL-NEXT: - S_OBJNAME [size = 20] sig=0, `* Linker *`
+ALL-NEXT: - S_COMPILE3 [size = 48]
+ALL-NEXT: machine = intel 80386, Ver = Microsoft (R) LINK, language = link
+ALL-NEXT: frontend = 0.0.0.0, backend = 12.0.31101.0
+ALL-NEXT: flags = none
+ALL-NEXT: - S_ENVBLOCK [size = 172]
+ALL-NEXT: - cwd
+ALL-NEXT: - d:\src\llvm\test\DebugInfo\PDB\Inputs
+ALL-NEXT: - exe
+ALL-NEXT: - C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\link.exe
+ALL-NEXT: - pdb
+ALL-NEXT: - d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.pdb
+ALL-NEXT: - S_TRAMPOLINE [size = 20]
+ALL-NEXT: type = tramp incremental, size = 5, source = 0001:0005, target = 0001:0005
+ALL-NEXT: - S_SECTION [size = 28] `.text`
+ALL-NEXT: length = 4122, alignment = 12, rva = 4096, section # = 1, characteristics = 1610612768
+ALL-NEXT: - S_COFFGROUP [size = 28] `.text$mn`
+ALL-NEXT: length = 4122, addr = 0001:0000, characteristics = 1610612768
+ALL-NEXT: - S_SECTION [size = 28] `.rdata`
+ALL-NEXT: length = 690, alignment = 12, rva = 12288, section # = 2, characteristics = 1073741888
+ALL-NEXT: - S_COFFGROUP [size = 28] `.rdata`
+ALL-NEXT: length = 323, addr = 0002:0000, characteristics = 1073741888
+ALL-NEXT: - S_COFFGROUP [size = 28] `.edata`
+ALL-NEXT: length = 0, addr = 0002:0323, characteristics = 1073741888
+ALL-NEXT: - S_COFFGROUP [size = 32] `.rdata$debug`
+ALL-NEXT: length = 366, addr = 0002:0324, characteristics = 1073741888
+ALL-NEXT: - S_SECTION [size = 28] `.data`
+ALL-NEXT: length = 4, alignment = 12, rva = 16384, section # = 3, characteristics = 3221225536
+ALL-NEXT: - S_COFFGROUP [size = 24] `.bss`
+ALL-NEXT: length = 4, addr = 0003:0000, characteristics = 3221225600
+ALL-NEXT: - S_SECTION [size = 28] `.reloc`
+ALL-NEXT: length = 8, alignment = 12, rva = 20480, section # = 4, characteristics = 1107296320
+ALL: Section Contributions
+ALL-NEXT: ============================================================
+ALL-NEXT: SC | mod = 1, 0001:0000, size = 10, data crc = 0, reloc crc = 0
+ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
+ALL-NEXT: SC | mod = 0, 0001:0016, size = 10, data crc = 3617027124, reloc crc = 0
+ALL-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_16BYTES | IMAGE_SCN_MEM_EXECUTE |
+ALL-NEXT: IMAGE_SCN_MEM_READ
+ALL-NEXT: SC | mod = 1, 0002:0000, size = 56, data crc = 0, reloc crc = 0
+ALL-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
+ALL-NEXT: SC | mod = 1, 0002:0324, size = 72, data crc = 0, reloc crc = 0
+ALL-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ
+ALL-NEXT: SC | mod = 1, 0002:0396, size = 20, data crc = 0, reloc crc = 0
+ALL-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ
+ALL-NEXT: SC | mod = 0, 0003:0000, size = 4, data crc = 0, reloc crc = 0
+ALL-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ |
+ALL-NEXT: IMAGE_SCN_MEM_WRITE
+ALL: Section Map
+ALL-NEXT: ============================================================
+ALL-NEXT: Section 0000 | ovl = 0, group = 0, frame = 0, name = 1
+ALL-NEXT: class = 65535, offset = 0, size = 4122
+ALL-NEXT: flags = read | execute | 32 bit addr | selector
+ALL-NEXT: Section 0001 | ovl = 1, group = 0, frame = 0, name = 2
+ALL-NEXT: class = 65535, offset = 0, size = 690
+ALL-NEXT: flags = read | 32 bit addr | selector
+ALL-NEXT: Section 0002 | ovl = 2, group = 0, frame = 0, name = 3
+ALL-NEXT: class = 65535, offset = 0, size = 4
+ALL-NEXT: flags = read | write | 32 bit addr | selector
+ALL-NEXT: Section 0003 | ovl = 3, group = 0, frame = 0, name = 4
+ALL-NEXT: class = 65535, offset = 0, size = 8
+ALL-NEXT: flags = read | 32 bit addr | selector
+ALL-NEXT: Section 0004 | ovl = 4, group = 0, frame = 0, name = 0
+ALL-NEXT: class = 65535, offset = 0, size = 4294967295
+ALL-NEXT: flags = 32 bit addr | absolute addr
-; ALL: FileHeaders {
-; ALL: BlockSize: 4096
-; ALL: FreeBlockMap: 2
-; ALL: NumBlocks: 25
-; ALL: NumDirectoryBytes: 136
-; ALL: Unknown1: 0
-; ALL: BlockMapAddr: 24
-; ALL: NumDirectoryBlocks: 1
-; ALL: DirectoryBlocks: [23]
-; ALL: NumStreams: 17
-; ALL: }
-; ALL: Streams [
-; ALL: Stream 0: [Old MSF Directory] (40 bytes)
-; ALL: Stream 1: [PDB Stream] (118 bytes)
-; ALL: Stream 2: [TPI Stream] (5392 bytes)
-; ALL: Stream 3: [DBI Stream] (739 bytes)
-; ALL: Stream 4: [IPI Stream] (784 bytes)
-; ALL: Stream 5: [Named Stream "/LinkInfo"] (0 bytes)
-; ALL: Stream 6: [Global Symbol Hash] (556 bytes)
-; ALL: Stream 7: [Public Symbol Hash] (604 bytes)
-; ALL: Stream 8: [Public Symbol Records] (104 bytes)
-; ALL: Stream 9: [Named Stream "/src/headerblock"] (0 bytes)
-; ALL: Stream 10: [Section Header Data] (160 bytes)
-; ALL: Stream 11: [New FPO Data] (32 bytes)
-; ALL: Stream 12: [Module "d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj"] (308 bytes)
-; ALL: Stream 13: [Named Stream "/names"] (239 bytes)
-; ALL: Stream 14: [Module "* Linker *"] (520 bytes)
-; ALL: Stream 15: [TPI Hash] (308 bytes)
-; ALL: Stream 16: [IPI Hash] (68 bytes)
-; ALL: ]
-; ALL: Msf Free Pages: [3, 4, 5, 8, 9]
-; ALL: Orphaned Pages: []
-; ALL: Multiply Used Pages: []
-; ALL: Use After Free Pages: []
-; ALL: StreamBlocks [
-; ALL: Stream 0: [8]
-; ALL: Stream 1: [19]
-; ALL: Stream 2: [18, 17]
-; ALL: Stream 3: [14]
-; ALL: Stream 4: [20]
-; ALL: Stream 5: []
-; ALL: Stream 6: [11]
-; ALL: Stream 7: [13]
-; ALL: Stream 8: [12]
-; ALL: Stream 9: []
-; ALL: Stream 10: [10]
-; ALL: Stream 11: [15]
-; ALL: Stream 12: [6]
-; ALL: Stream 13: [16]
-; ALL: Stream 14: [7]
-; ALL: Stream 15: [21]
-; ALL: Stream 16: [22]
-; ALL: ]
-; ALL: PDB Stream {
-; ALL: Version: 20000404
-; ALL: Signature: 0x54E507E2
-; ALL: Age: 1
-; ALL: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
-; ALL: Features: 0x1
-; ALL: }
-; ALL: Type Info Stream (IPI) {
-; ALL: IPI Version: 20040203
-; ALL: Record count: 15
-; ALL: Records [
-; ALL: {
-; ALL: UdtModSourceLine (0x1000) {
-; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; ALL: UDT: __vc_attributes::threadingAttribute (0x100B)
-; ALL: SourceFile: <unknown simple type> (0x1)
-; ALL: LineNumber: 481
-; ALL: Module: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: UdtModSourceLine (0x1001) {
-; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; ALL: UDT: __vc_attributes::event_receiverAttribute (0x1017)
-; ALL: SourceFile: <unknown simple type> (0x1)
-; ALL: LineNumber: 194
-; ALL: Module: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: UdtModSourceLine (0x1002) {
-; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; ALL: UDT: __vc_attributes::aggregatableAttribute (0x1021)
-; ALL: SourceFile: <unknown simple type> (0x1)
-; ALL: LineNumber: 603
-; ALL: Module: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: UdtModSourceLine (0x1003) {
-; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; ALL: UDT: __vc_attributes::event_sourceAttribute (0x102C)
-; ALL: SourceFile: <unknown simple type> (0x1)
-; ALL: LineNumber: 1200
-; ALL: Module: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: UdtModSourceLine (0x1004) {
-; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; ALL: UDT: __vc_attributes::moduleAttribute (0x103A)
-; ALL: SourceFile: <unknown simple type> (0x1)
-; ALL: LineNumber: 540
-; ALL: Module: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: UdtModSourceLine (0x1005) {
-; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; ALL: UDT: __vc_attributes::helper_attributes::usageAttribute (0x1042)
-; ALL: SourceFile: <unknown simple type> (0x1)
-; ALL: LineNumber: 108
-; ALL: Module: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: UdtModSourceLine (0x1006) {
-; ALL: TypeLeafKind: LF_UDT_MOD_SRC_LINE (0x1607)
-; ALL: UDT: __vc_attributes::helper_attributes::v1_alttypeAttribute (0x104A)
-; ALL: SourceFile: <unknown simple type> (0x1)
-; ALL: LineNumber: 96
-; ALL: Module: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: StringId (0x1007) {
-; ALL: TypeLeafKind: LF_STRING_ID (0x1605)
-; ALL: Id: 0x0
-; ALL: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: StringId (0x1008) {
-; ALL: TypeLeafKind: LF_STRING_ID (0x1605)
-; ALL: Id: 0x0
-; ALL: StringData: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: StringId (0x1009) {
-; ALL: TypeLeafKind: LF_STRING_ID (0x1605)
-; ALL: Id: 0x0
-; ALL: StringData: empty.cpp
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: StringId (0x100A) {
-; ALL: TypeLeafKind: LF_STRING_ID (0x1605)
-; ALL: Id: 0x0
-; ALL: StringData: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: StringId (0x100B) {
-; ALL: TypeLeafKind: LF_STRING_ID (0x1605)
-; ALL: Id: 0x0
-; ALL: StringData: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: StringList (0x100C) {
-; ALL: TypeLeafKind: LF_SUBSTR_LIST (0x1604)
-; ALL: NumStrings: 1
-; ALL: Strings [
-; ALL: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows (0x100B)
-; ALL: ]
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: StringId (0x100D) {
-; ALL: TypeLeafKind: LF_STRING_ID (0x1605)
-; ALL: Id: "-Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows" (0x100C)
-; ALL: StringData: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: BuildInfo (0x100E) {
-; ALL: TypeLeafKind: LF_BUILDINFO (0x1603)
-; ALL: NumArgs: 5
-; ALL: Arguments [
-; ALL: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs (0x1007)
-; ALL: ArgType: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\cl.exe (0x1008)
-; ALL: ArgType: empty.cpp (0x1009)
-; ALL: ArgType: d:\src\llvm\test\DebugInfo\PDB\Inputs\vc120.pdb (0x100A)
-; ALL: ArgType: Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TP -X (0x100D)
-; ALL: ]
-; ALL: }
-; ALL: }
-; ALL: ]
-; ALL: }
-; ALL: DBI Stream {
-; ALL: Dbi Version: 19990903
-; ALL: Age: 1
-; ALL: Incremental Linking: Yes
-; ALL: Has CTypes: No
-; ALL: Is Stripped: No
-; ALL: Machine Type: x86
-; ALL: Symbol Record Stream Index: 8
-; ALL: Public Symbol Stream Index: 7
-; ALL: Global Symbol Stream Index: 6
-; ALL: Toolchain Version: 12.0
-; ALL: mspdb120.dll version: 12.0.31101
-; ALL: Modules [
-; ALL: {
-; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; ALL: Debug Stream Index: 12
-; ALL: Object File Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; ALL: Num Files: 1
-; ALL: Source File Name Idx: 0
-; ALL: Pdb File Name Idx: 0
-; ALL: Line Info Byte Size: 0
-; ALL: C13 Line Info Byte Size: 88
-; ALL: Symbol Byte Size: 208
-; ALL: Type Server Index: 0
-; ALL: Has EC Info: No
-; ALL: 1 Contributing Source Files [
-; ALL: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-; ALL: ]
-; ALL: Symbols [
-; ALL: {
-; ALL: ObjectName {
-; ALL: Signature: 0x0
-; ALL: ObjectName: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: CompilerFlags3 {
-; ALL: Language: Cpp (0x1)
-; ALL: Flags [ (0x2000)
-; ALL: SecurityChecks (0x2000)
-; ALL: ]
-; ALL: Machine: Pentium3 (0x7)
-; ALL: FrontendVersion: 18.0.31101.0
-; ALL: BackendVersion: 18.0.31101.0
-; ALL: VersionName: Microsoft (R) Optimizing Compiler
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: ProcStart {
-; ALL: PtrParent: 0x0
-; ALL: PtrEnd: 0xC4
-; ALL: PtrNext: 0x0
-; ALL: CodeSize: 0xA
-; ALL: DbgStart: 0x3
-; ALL: DbgEnd: 0x8
-; ALL: FunctionType: int () (0x1001)
-; ALL: Segment: 0x1
-; ALL: Flags [ (0x1)
-; ALL: HasFP (0x1)
-; ALL: ]
-; ALL: DisplayName: main
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: FrameProc {
-; ALL: TotalFrameBytes: 0x0
-; ALL: PaddingFrameBytes: 0x0
-; ALL: OffsetToPadding: 0x0
-; ALL: BytesOfCalleeSavedRegisters: 0x0
-; ALL: OffsetOfExceptionHandler: 0x0
-; ALL: SectionIdOfExceptionHandler: 0x0
-; ALL: Flags [ (0x128200)
-; ALL: AsynchronousExceptionHandling (0x200)
-; ALL: OptimizedForSpeed (0x100000)
-; ALL: ]
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: BlockEnd {
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: BuildInfo {
-; ALL: BuildId: 4110
-; ALL: }
-; ALL: }
-; ALL: ]
-; ALL: }
-; ALL: {
-; ALL: Name: * Linker *
-; ALL: Debug Stream Index: 14
-; ALL: Object File Name:
-; ALL: Num Files: 0
-; ALL: Source File Name Idx: 0
-; ALL: Pdb File Name Idx: 1
-; ALL: Line Info Byte Size: 0
-; ALL: C13 Line Info Byte Size: 0
-; ALL: Symbol Byte Size: 516
-; ALL: Type Server Index: 0
-; ALL: Has EC Info: No
-; ALL: 0 Contributing Source Files [
-; ALL: ]
-; ALL: Symbols [
-; ALL: {
-; ALL: ObjectName {
-; ALL: Signature: 0x0
-; ALL: ObjectName: * Linker *
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: CompilerFlags3 {
-; ALL: Language: Link (0x7)
-; ALL: Flags [ (0x0)
-; ALL: ]
-; ALL: Machine: Intel80386 (0x3)
-; ALL: FrontendVersion: 0.0.0.0
-; ALL: BackendVersion: 12.0.31101.0
-; ALL: VersionName: Microsoft (R) LINK
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: EnvBlock {
-; ALL: Entries [
-; ALL: cwd
-; ALL: d:\src\llvm\test\DebugInfo\PDB\Inputs
-; ALL: exe
-; ALL: C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\BIN\link.exe
-; ALL: pdb
-; ALL: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.pdb
-; ALL: ]
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: Trampoline {
-; ALL: Type: TrampIncremental (0x0)
-; ALL: Size: 5
-; ALL: ThunkOff: 5
-; ALL: TargetOff: 16
-; ALL: ThunkSection: 1
-; ALL: TargetSection: 1
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: Section {
-; ALL: SectionNumber: 1
-; ALL: Alignment: 12
-; ALL: Rva: 4096
-; ALL: Length: 4122
-; ALL: Characteristics [ (0x60000020)
-; ALL: IMAGE_SCN_CNT_CODE (0x20)
-; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Name: .text
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: COFF Group {
-; ALL: Size: 4122
-; ALL: Characteristics [ (0x60000020)
-; ALL: IMAGE_SCN_CNT_CODE (0x20)
-; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Offset: 0
-; ALL: Segment: 1
-; ALL: Name: .text$mn
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: Section {
-; ALL: SectionNumber: 2
-; ALL: Alignment: 12
-; ALL: Rva: 12288
-; ALL: Length: 690
-; ALL: Characteristics [ (0x40000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Name: .rdata
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: COFF Group {
-; ALL: Size: 323
-; ALL: Characteristics [ (0x40000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Offset: 0
-; ALL: Segment: 2
-; ALL: Name: .rdata
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: COFF Group {
-; ALL: Size: 0
-; ALL: Characteristics [ (0x40000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Offset: 323
-; ALL: Segment: 2
-; ALL: Name: .edata
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: COFF Group {
-; ALL: Size: 366
-; ALL: Characteristics [ (0x40000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Offset: 324
-; ALL: Segment: 2
-; ALL: Name: .rdata$debug
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: Section {
-; ALL: SectionNumber: 3
-; ALL: Alignment: 12
-; ALL: Rva: 16384
-; ALL: Length: 4
-; ALL: Characteristics [ (0xC0000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: IMAGE_SCN_MEM_WRITE (0x80000000)
-; ALL: ]
-; ALL: Name: .data
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: COFF Group {
-; ALL: Size: 4
-; ALL: Characteristics [ (0xC0000080)
-; ALL: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: IMAGE_SCN_MEM_WRITE (0x80000000)
-; ALL: ]
-; ALL: Offset: 0
-; ALL: Segment: 3
-; ALL: Name: .bss
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: Section {
-; ALL: SectionNumber: 4
-; ALL: Alignment: 12
-; ALL: Rva: 20480
-; ALL: Length: 8
-; ALL: Characteristics [ (0x42000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Name: .reloc
-; ALL: }
-; ALL: }
-; ALL: ]
-; ALL: }
-; ALL: ]
-; ALL: }
-; ALL: Section Contributions [
-; ALL: Contribution {
-; ALL: ISect: 1
-; ALL: Off: 0
-; ALL: Size: 10
-; ALL: Characteristics [ (0x60000020)
-; ALL: IMAGE_SCN_CNT_CODE (0x20)
-; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Module {
-; ALL: Index: 1
-; ALL: Name: * Linker *
-; ALL: }
-; ALL: Data CRC: 0
-; ALL: Reloc CRC: 0
-; ALL: }
-; ALL: Contribution {
-; ALL: ISect: 1
-; ALL: Off: 16
-; ALL: Size: 10
-; ALL: Characteristics [ (0x60500020)
-; ALL: IMAGE_SCN_ALIGN_16BYTES (0x500000)
-; ALL: IMAGE_SCN_CNT_CODE (0x20)
-; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Module {
-; ALL: Index: 0
-; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; ALL: }
-; ALL: Data CRC: 3617027124
-; ALL: Reloc CRC: 0
-; ALL: }
-; ALL: Contribution {
-; ALL: ISect: 2
-; ALL: Off: 0
-; ALL: Size: 56
-; ALL: Characteristics [ (0x40000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Module {
-; ALL: Index: 1
-; ALL: Name: * Linker *
-; ALL: }
-; ALL: Data CRC: 0
-; ALL: Reloc CRC: 0
-; ALL: }
-; ALL: Contribution {
-; ALL: ISect: 2
-; ALL: Off: 324
-; ALL: Size: 72
-; ALL: Characteristics [ (0x40300040)
-; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Module {
-; ALL: Index: 1
-; ALL: Name: * Linker *
-; ALL: }
-; ALL: Data CRC: 0
-; ALL: Reloc CRC: 0
-; ALL: }
-; ALL: Contribution {
-; ALL: ISect: 2
-; ALL: Off: 396
-; ALL: Size: 20
-; ALL: Characteristics [ (0x40300040)
-; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: Module {
-; ALL: Index: 1
-; ALL: Name: * Linker *
-; ALL: }
-; ALL: Data CRC: 0
-; ALL: Reloc CRC: 0
-; ALL: }
-; ALL: Contribution {
-; ALL: ISect: 3
-; ALL: Off: 0
-; ALL: Size: 4
-; ALL: Characteristics [ (0xC0300080)
-; ALL: IMAGE_SCN_ALIGN_4BYTES (0x300000)
-; ALL: IMAGE_SCN_CNT_UNINITIALIZED_DATA (0x80)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: IMAGE_SCN_MEM_WRITE (0x80000000)
-; ALL: ]
-; ALL: Module {
-; ALL: Index: 0
-; ALL: Name: d:\src\llvm\test\DebugInfo\PDB\Inputs\empty.obj
-; ALL: }
-; ALL: Data CRC: 0
-; ALL: Reloc CRC: 0
-; ALL: }
-; ALL: ]
-; ALL: Section Map [
-; ALL: Entry {
-; ALL: Flags [ (0x10D)
-; ALL: AddressIs32Bit (0x8)
-; ALL: Execute (0x4)
-; ALL: IsSelector (0x100)
-; ALL: Read (0x1)
-; ALL: ]
-; ALL: Ovl: 0
-; ALL: Group: 0
-; ALL: Frame: 1
-; ALL: SecName: 65535
-; ALL: ClassName: 65535
-; ALL: Offset: 0
-; ALL: SecByteLength: 4122
-; ALL: }
-; ALL: Entry {
-; ALL: Flags [ (0x109)
-; ALL: AddressIs32Bit (0x8)
-; ALL: IsSelector (0x100)
-; ALL: Read (0x1)
-; ALL: ]
-; ALL: Ovl: 0
-; ALL: Group: 0
-; ALL: Frame: 2
-; ALL: SecName: 65535
-; ALL: ClassName: 65535
-; ALL: Offset: 0
-; ALL: SecByteLength: 690
-; ALL: }
-; ALL: Entry {
-; ALL: Flags [ (0x10B)
-; ALL: AddressIs32Bit (0x8)
-; ALL: IsSelector (0x100)
-; ALL: Read (0x1)
-; ALL: Write (0x2)
-; ALL: ]
-; ALL: Ovl: 0
-; ALL: Group: 0
-; ALL: Frame: 3
-; ALL: SecName: 65535
-; ALL: ClassName: 65535
-; ALL: Offset: 0
-; ALL: SecByteLength: 4
-; ALL: }
-; ALL: Entry {
-; ALL: Flags [ (0x109)
-; ALL: AddressIs32Bit (0x8)
-; ALL: IsSelector (0x100)
-; ALL: Read (0x1)
-; ALL: ]
-; ALL: Ovl: 0
-; ALL: Group: 0
-; ALL: Frame: 4
-; ALL: SecName: 65535
-; ALL: ClassName: 65535
-; ALL: Offset: 0
-; ALL: SecByteLength: 8
-; ALL: }
-; ALL: Entry {
-; ALL: Flags [ (0x208)
-; ALL: AddressIs32Bit (0x8)
-; ALL: IsAbsoluteAddress (0x200)
-; ALL: ]
-; ALL: Ovl: 0
-; ALL: Group: 0
-; ALL: Frame: 0
-; ALL: SecName: 65535
-; ALL: ClassName: 65535
-; ALL: Offset: 0
-; ALL: SecByteLength: 4294967295
-; ALL: }
-; ALL: ]
-; ALL: Globals Stream {
-; ALL: Stream number: 6
-; ALL: Number of buckets: 2
-; ALL: Hash Buckets: [0, 12]
-; ALL: }
-; ALL: Publics Stream {
-; ALL: Stream number: 7
-; ALL: SymHash: 556
-; ALL: AddrMap: 8
-; ALL: Number of buckets: 2
-; ALL: Hash Buckets: [0, 12]
-; ALL: Address Map: [36, 0]
-; ALL: Thunk Map: [4112]
-; ALL: Section Offsets: [4096, 1]
-; ALL: Symbols [
-; ALL: {
-; ALL: PublicSym {
-; ALL: Type: 0
-; ALL: Seg: 3
-; ALL: Off: 0
-; ALL: Name: ?__purecall@@3PAXA
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: PublicSym {
-; ALL: Type: 2
-; ALL: Seg: 1
-; ALL: Off: 16
-; ALL: Name: _main
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: ProcRef {
-; ALL: SumName: 0
-; ALL: SymOffset: 120
-; ALL: Mod: 1
-; ALL: Name: main
-; ALL: }
-; ALL: }
-; ALL: {
-; ALL: DataSym {
-; ALL: Type: void* (0x403)
-; ALL: DisplayName: __purecall
-; ALL: }
-; ALL: }
-; ALL: ]
-; ALL: }
-; ALL: Section Headers [
-; ALL: {
-; ALL: Name: .text
-; ALL: Virtual Size: 4122
-; ALL: Virtual Address: 4096
-; ALL: Size of Raw Data: 4608
-; ALL: File Pointer to Raw Data: 1024
-; ALL: File Pointer to Relocations: 0
-; ALL: File Pointer to Linenumbers: 0
-; ALL: Number of Relocations: 0
-; ALL: Number of Linenumbers: 0
-; ALL: Characteristics [ (0x60000020)
-; ALL: IMAGE_SCN_CNT_CODE (0x20)
-; ALL: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: }
-; ALL: {
-; ALL: Name: .rdata
-; ALL: Virtual Size: 690
-; ALL: Virtual Address: 12288
-; ALL: Size of Raw Data: 1024
-; ALL: File Pointer to Raw Data: 5632
-; ALL: File Pointer to Relocations: 0
-; ALL: File Pointer to Linenumbers: 0
-; ALL: Number of Relocations: 0
-; ALL: Number of Linenumbers: 0
-; ALL: Characteristics [ (0x40000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: }
-; ALL: {
-; ALL: Name: .data
-; ALL: Virtual Size: 4
-; ALL: Virtual Address: 16384
-; ALL: Size of Raw Data: 0
-; ALL: File Pointer to Raw Data: 0
-; ALL: File Pointer to Relocations: 0
-; ALL: File Pointer to Linenumbers: 0
-; ALL: Number of Relocations: 0
-; ALL: Number of Linenumbers: 0
-; ALL: Characteristics [ (0xC0000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: IMAGE_SCN_MEM_WRITE (0x80000000)
-; ALL: ]
-; ALL: }
-; ALL: {
-; ALL: Name: .reloc
-; ALL: Virtual Size: 8
-; ALL: Virtual Address: 20480
-; ALL: Size of Raw Data: 512
-; ALL: File Pointer to Raw Data: 6656
-; ALL: File Pointer to Relocations: 0
-; ALL: File Pointer to Linenumbers: 0
-; ALL: Number of Relocations: 0
-; ALL: Number of Linenumbers: 0
-; ALL: Characteristics [ (0x42000040)
-; ALL: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-; ALL: IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
-; ALL: IMAGE_SCN_MEM_READ (0x40000000)
-; ALL: ]
-; ALL: }
-; ALL: ]
-; BIG: FileHeaders {
-; BIG-NEXT: BlockSize: 4096
-; BIG-NEXT: FreeBlockMap: 2
-; BIG-NEXT: NumBlocks: 99
-; BIG-NEXT: NumDirectoryBytes: 616
-; BIG-NEXT: Unknown1: 0
-; BIG-NEXT: BlockMapAddr: 97
-; BIG-NEXT: NumDirectoryBlocks: 1
-; BIG-NEXT: DirectoryBlocks: [96]
-; BIG-NEXT: NumStreams: 64
-; BIG-NEXT: }
-; BIG-NEXT: PDB Stream {
-; BIG-NEXT: Version: 20000404
-; BIG-NEXT: Signature: 0x571FFE67
-; BIG-NEXT: Age: 1
-; BIG-NEXT: Guid: {880ECC89-DF81-0B4F-839C-58CBD052E937}
-; BIG-NEXT: Features: 0x1
-; BIG-NEXT: Named Streams {
-; BIG-NEXT: /names: 13
-; BIG-NEXT: /LinkInfo: 5
-; BIG-NEXT: /src/headerblock: 61
-; BIG-NEXT: }
-; BIG-NEXT: }
-; BIG-NEXT: DBI Stream {
-; BIG-NEXT: Dbi Version: 19990903
-; BIG-NEXT: Age: 1
-; BIG-NEXT: Incremental Linking: Yes
-; BIG-NEXT: Has CTypes: No
-; BIG-NEXT: Is Stripped: No
-; BIG-NEXT: Machine Type: x86
-; BIG-NEXT: Symbol Record Stream Index: 9
-; BIG-NEXT: Public Symbol Stream Index: 8
-; BIG-NEXT: Global Symbol Stream Index: 7
-; BIG-NEXT: Toolchain Version: 14.0
-; BIG-NEXT: mspdb140.dll version: 14.0.23918
-; BIG-NEXT: Modules [
-; BIG-NEXT: {
-; BIG-NEXT: Name: D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj
-; BIG-NEXT: Debug Stream Index: 12
-; BIG-NEXT: Object File Name: D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 400
-; BIG-NEXT: Symbol Byte Size: 872
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: d:\src\llvm\test\tools\llvm-symbolizer\pdb\inputs\test.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj
-; BIG-NEXT: Debug Stream Index: 14
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 14
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 344
-; BIG-NEXT: Symbol Byte Size: 720
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 14 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\misc\i386\cpu_disp.c
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj
-; BIG-NEXT: Debug Stream Index: 15
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 19
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 464
-; BIG-NEXT: Symbol Byte Size: 464
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 19 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\rtc\initsect.cpp
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj
-; BIG-NEXT: Debug Stream Index: 16
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 1
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 32
-; BIG-NEXT: Symbol Byte Size: 444
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\i386\sehprolg4.asm
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj
-; BIG-NEXT: Debug Stream Index: 17
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 14
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 344
-; BIG-NEXT: Symbol Byte Size: 604
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 14 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\i386\chandler4gs.c
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj
-; BIG-NEXT: Debug Stream Index: 18
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 14
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 344
-; BIG-NEXT: Symbol Byte Size: 344
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 14 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\i386\secchk.c
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj
-; BIG-NEXT: Debug Stream Index: 19
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 9
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 224
-; BIG-NEXT: Symbol Byte Size: 160
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 9 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj
-; BIG-NEXT: Debug Stream Index: 20
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 14
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 1392
-; BIG-NEXT: Symbol Byte Size: 1144
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 14 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\gs\gs_report.c
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj
-; BIG-NEXT: Debug Stream Index: 21
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 10
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 432
-; BIG-NEXT: Symbol Byte Size: 552
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 10 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\gs\gs_support.c
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj
-; BIG-NEXT: Debug Stream Index: 22
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 14
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 392
-; BIG-NEXT: Symbol Byte Size: 328
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 14 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\misc\checkcfg.c
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj
-; BIG-NEXT: Debug Stream Index: 23
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 10
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 352
-; BIG-NEXT: Symbol Byte Size: 424
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 10 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\misc\guard_support.c
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj
-; BIG-NEXT: Debug Stream Index: 24
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 9
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 224
-; BIG-NEXT: Symbol Byte Size: 156
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 9 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj
-; BIG-NEXT: Debug Stream Index: 25
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 11
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 328
-; BIG-NEXT: Symbol Byte Size: 272
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 11 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_dtor.c
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj
-; BIG-NEXT: Debug Stream Index: 26
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 10
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 304
-; BIG-NEXT: Symbol Byte Size: 272
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 10 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_init.c
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj
-; BIG-NEXT: Debug Stream Index: 27
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 276
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\matherr_detection.c
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj
-; BIG-NEXT: Debug Stream Index: 28
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 268
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\ucrt_detection.c
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj
-; BIG-NEXT: Debug Stream Index: 29
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 260
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\argv_mode.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj
-; BIG-NEXT: Debug Stream Index: 30
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 260
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\commit_mode.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj
-; BIG-NEXT: Debug Stream Index: 31
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 24
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 760
-; BIG-NEXT: Symbol Byte Size: 620
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 24 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\default_local_stdio_options.cpp
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdio.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vadefs.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj
-; BIG-NEXT: Debug Stream Index: 32
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 80
-; BIG-NEXT: Symbol Byte Size: 272
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\denormal_control.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj
-; BIG-NEXT: Debug Stream Index: 33
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 268
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\env_mode.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj
-; BIG-NEXT: Debug Stream Index: 34
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 260
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\file_mode.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj
-; BIG-NEXT: Debug Stream Index: 35
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 80
-; BIG-NEXT: Symbol Byte Size: 292
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\invalid_parameter_handler.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj
-; BIG-NEXT: Debug Stream Index: 36
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 2
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 112
-; BIG-NEXT: Symbol Byte Size: 312
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 2 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\matherr.cpp
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj
-; BIG-NEXT: Debug Stream Index: 37
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 260
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\new_mode.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj
-; BIG-NEXT: Debug Stream Index: 38
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 88
-; BIG-NEXT: Symbol Byte Size: 272
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\thread_locale.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj
-; BIG-NEXT: Debug Stream Index: 39
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 21
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 624
-; BIG-NEXT: Symbol Byte Size: 432
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 21 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\eh\tncleanup.cpp
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_typeinfo.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_exception.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj
-; BIG-NEXT: Debug Stream Index: 40
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 26
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 1668
-; BIG-NEXT: Symbol Byte Size: 2364
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 26 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdio.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vadefs.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj
-; BIG-NEXT: Debug Stream Index: 41
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 20
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 488
-; BIG-NEXT: Symbol Byte Size: 196
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 20 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj
-; BIG-NEXT: Debug Stream Index: 42
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 20
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 2500
-; BIG-NEXT: Symbol Byte Size: 6020
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 20 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\utility.cpp
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj
-; BIG-NEXT: Debug Stream Index: 43
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 1
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 368
-; BIG-NEXT: Symbol Byte Size: 988
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 1 Contributing Source Files [
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\ucrt_stubs.cpp
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj
-; BIG-NEXT: Debug Stream Index: 44
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 20
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 1240
-; BIG-NEXT: Symbol Byte Size: 1844
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 20 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\utility\utility_desktop.cpp
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj
-; BIG-NEXT: Debug Stream Index: 45
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib
-; BIG-NEXT: Num Files: 20
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 552
-; BIG-NEXT: Symbol Byte Size: 356
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 20 Contributing Source Files [
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\string.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\src\defaults\default_precision.cpp
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\malloc.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
-; BIG-NEXT: f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
-; BIG-NEXT: f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\math.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\stdlib.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\ctype.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
-; BIG-NEXT: f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
-; BIG-NEXT: f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: Import:KERNEL32.dll
-; BIG-NEXT: Debug Stream Index: 47
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 1616
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: KERNEL32.dll
-; BIG-NEXT: Debug Stream Index: 46
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 208
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: Import:VCRUNTIME140.dll
-; BIG-NEXT: Debug Stream Index: 49
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 664
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: VCRUNTIME140.dll
-; BIG-NEXT: Debug Stream Index: 48
-; BIG-NEXT: Object File Name: C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 148
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: Import:api-ms-win-crt-stdio-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 59
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 264
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: api-ms-win-crt-stdio-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 58
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 180
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: Import:api-ms-win-crt-runtime-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 57
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 3068
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: api-ms-win-crt-runtime-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 56
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 188
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: Import:api-ms-win-crt-math-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 55
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 140
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: api-ms-win-crt-math-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 54
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 180
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: Import:api-ms-win-crt-locale-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 53
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 148
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: api-ms-win-crt-locale-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 52
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 188
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: Import:api-ms-win-crt-heap-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 51
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 136
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: api-ms-win-crt-heap-l1-1-0.dll
-; BIG-NEXT: Debug Stream Index: 50
-; BIG-NEXT: Object File Name: C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 0
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 180
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: {
-; BIG-NEXT: Name: * Linker *
-; BIG-NEXT: Debug Stream Index: 60
-; BIG-NEXT: Object File Name:
-; BIG-NEXT: Num Files: 0
-; BIG-NEXT: Source File Name Idx: 0
-; BIG-NEXT: Pdb File Name Idx: 55
-; BIG-NEXT: Line Info Byte Size: 0
-; BIG-NEXT: C13 Line Info Byte Size: 0
-; BIG-NEXT: Symbol Byte Size: 3080
-; BIG-NEXT: Type Server Index: 0
-; BIG-NEXT: Has EC Info: No
-; BIG-NEXT: 0 Contributing Source Files [
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BIG-NEXT: ]
-; BIG-NEXT: }
-; BAD-BLOCK-SIZE: Native PDB Error: The PDB file is corrupt. Does not contain superblock
+BIG: Summary
+BIG-NEXT: ============================================================
+BIG-NEXT: Block Size: 4096
+BIG-NEXT: Number of blocks: 99
+BIG-NEXT: Number of streams: 64
+BIG-NEXT: Signature: 1461714535
+BIG-NEXT: Age: 1
+BIG-NEXT: GUID: {880ECC89-DF81-0B4F-839C-58CBD052E937}
+BIG-NEXT: Features: 0x1
+BIG-NEXT: Has Debug Info: true
+BIG-NEXT: Has Types: true
+BIG-NEXT: Has IDs: true
+BIG-NEXT: Has Globals: true
+BIG-NEXT: Has Publics: true
+BIG-NEXT: Is incrementally linked: true
+BIG-NEXT: Has conflicting types: false
+BIG-NEXT: Is stripped: false
+BIG: Modules
+BIG-NEXT: ============================================================
+BIG-NEXT: Mod 0000 | Name: `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`:
+BIG-NEXT: Obj: `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`:
+BIG-NEXT: debug stream: 12, # files: 1, has ec info: false
+BIG-NEXT: Mod 0001 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 14, # files: 14, has ec info: false
+BIG-NEXT: Mod 0002 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 15, # files: 19, has ec info: false
+BIG-NEXT: Mod 0003 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 16, # files: 1, has ec info: false
+BIG-NEXT: Mod 0004 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 17, # files: 14, has ec info: false
+BIG-NEXT: Mod 0005 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 18, # files: 14, has ec info: false
+BIG-NEXT: Mod 0006 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 19, # files: 9, has ec info: false
+BIG-NEXT: Mod 0007 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 20, # files: 14, has ec info: false
+BIG-NEXT: Mod 0008 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 21, # files: 10, has ec info: false
+BIG-NEXT: Mod 0009 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 22, # files: 14, has ec info: false
+BIG-NEXT: Mod 0010 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 23, # files: 10, has ec info: false
+BIG-NEXT: Mod 0011 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 24, # files: 9, has ec info: false
+BIG-NEXT: Mod 0012 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 25, # files: 11, has ec info: false
+BIG-NEXT: Mod 0013 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 26, # files: 10, has ec info: false
+BIG-NEXT: Mod 0014 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 27, # files: 1, has ec info: false
+BIG-NEXT: Mod 0015 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 28, # files: 1, has ec info: false
+BIG-NEXT: Mod 0016 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 29, # files: 1, has ec info: false
+BIG-NEXT: Mod 0017 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 30, # files: 1, has ec info: false
+BIG-NEXT: Mod 0018 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 31, # files: 24, has ec info: false
+BIG-NEXT: Mod 0019 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 32, # files: 1, has ec info: false
+BIG-NEXT: Mod 0020 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 33, # files: 1, has ec info: false
+BIG-NEXT: Mod 0021 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 34, # files: 1, has ec info: false
+BIG-NEXT: Mod 0022 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 35, # files: 1, has ec info: false
+BIG-NEXT: Mod 0023 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 36, # files: 2, has ec info: false
+BIG-NEXT: Mod 0024 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 37, # files: 1, has ec info: false
+BIG-NEXT: Mod 0025 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 38, # files: 1, has ec info: false
+BIG-NEXT: Mod 0026 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 39, # files: 21, has ec info: false
+BIG-NEXT: Mod 0027 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 40, # files: 26, has ec info: false
+BIG-NEXT: Mod 0028 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 41, # files: 20, has ec info: false
+BIG-NEXT: Mod 0029 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 42, # files: 20, has ec info: false
+BIG-NEXT: Mod 0030 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 43, # files: 1, has ec info: false
+BIG-NEXT: Mod 0031 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 44, # files: 20, has ec info: false
+BIG-NEXT: Mod 0032 | Name: `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\MSVCRT.lib`:
+BIG-NEXT: debug stream: 45, # files: 20, has ec info: false
+BIG-NEXT: Mod 0033 | Name: `Import:KERNEL32.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib`:
+BIG-NEXT: debug stream: 47, # files: 0, has ec info: false
+BIG-NEXT: Mod 0034 | Name: `KERNEL32.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\um\x86\kernel32.lib`:
+BIG-NEXT: debug stream: 46, # files: 0, has ec info: false
+BIG-NEXT: Mod 0035 | Name: `Import:VCRUNTIME140.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib`:
+BIG-NEXT: debug stream: 49, # files: 0, has ec info: false
+BIG-NEXT: Mod 0036 | Name: `VCRUNTIME140.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\MI0E91~1.0\VC\LIB\vcruntime.lib`:
+BIG-NEXT: debug stream: 48, # files: 0, has ec info: false
+BIG-NEXT: Mod 0037 | Name: `Import:api-ms-win-crt-stdio-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 59, # files: 0, has ec info: false
+BIG-NEXT: Mod 0038 | Name: `api-ms-win-crt-stdio-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 58, # files: 0, has ec info: false
+BIG-NEXT: Mod 0039 | Name: `Import:api-ms-win-crt-runtime-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 57, # files: 0, has ec info: false
+BIG-NEXT: Mod 0040 | Name: `api-ms-win-crt-runtime-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 56, # files: 0, has ec info: false
+BIG-NEXT: Mod 0041 | Name: `Import:api-ms-win-crt-math-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 55, # files: 0, has ec info: false
+BIG-NEXT: Mod 0042 | Name: `api-ms-win-crt-math-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 54, # files: 0, has ec info: false
+BIG-NEXT: Mod 0043 | Name: `Import:api-ms-win-crt-locale-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 53, # files: 0, has ec info: false
+BIG-NEXT: Mod 0044 | Name: `api-ms-win-crt-locale-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 52, # files: 0, has ec info: false
+BIG-NEXT: Mod 0045 | Name: `Import:api-ms-win-crt-heap-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 51, # files: 0, has ec info: false
+BIG-NEXT: Mod 0046 | Name: `api-ms-win-crt-heap-l1-1-0.dll`:
+BIG-NEXT: Obj: `C:\PROGRA~2\WI3CF2~1\10\Lib\10.0.10586.0\ucrt\x86\ucrt.lib`:
+BIG-NEXT: debug stream: 50, # files: 0, has ec info: false
+BIG-NEXT: Mod 0047 | Name: `* Linker *`:
+BIG-NEXT: Obj: ``:
+BIG-NEXT: debug stream: 60, # files: 0, has ec info: false
+BIG: Files
+BIG-NEXT: ============================================================
+BIG-NEXT: Mod 0000 | `D:\src\llvm\test\tools\llvm-symbolizer\pdb\Inputs\test.obj`:
+BIG-NEXT: - (MD5: A20261917ADC01A12CBDBF778BC6CCC8) d:\src\llvm\test\tools\llvm-symbolizer\pdb\inputs\test.cpp
+BIG-NEXT: Mod 0001 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_cpu_disp_.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: 884E12AC852D3B4E1E625A0F01595A68) f:\dd\vctools\crt\vcstartup\src\misc\i386\cpu_disp.c
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: Mod 0002 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_initsect_.obj`:
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: DD3FFC8C4284997F6762C449313244B2) f:\dd\vctools\crt\vcstartup\src\rtc\initsect.cpp
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: Mod 0003 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_sehprolg4_.obj`:
+BIG-NEXT: - (MD5: E562BB073C88A6A3791CE9FBDC64E7A7) f:\dd\vctools\crt\vcstartup\src\eh\i386\sehprolg4.asm
+BIG-NEXT: Mod 0004 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_chandler4gs_.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: D014BFD91FD6D4163AF92452CBC9EEA0) f:\dd\vctools\crt\vcstartup\src\eh\i386\chandler4gs.c
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: Mod 0005 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\_secchk_.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: 6C34B4E5ACA82CB0D6BD6CB8C059C9C9) f:\dd\vctools\crt\vcstartup\src\eh\i386\secchk.c
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: Mod 0006 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_cookie.obj`:
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: Mod 0007 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_report.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: 87566AA39C18DD3CEAC021002D34B63D) f:\dd\vctools\crt\vcstartup\src\gs\gs_report.c
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: Mod 0008 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\gs_support.obj`:
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: 57AC84319EF78F67DAA9372FDA8CBFCC) f:\dd\vctools\crt\vcstartup\src\gs\gs_support.c
+BIG-NEXT: Mod 0009 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\checkcfg.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: 9552C4FC4125F9D7D3A8B5FD18B7BCCF) f:\dd\vctools\crt\vcstartup\src\misc\checkcfg.c
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: Mod 0010 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\guard_support.obj`:
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: 8BFBA3D0672A148A9FB0E9F0A6BC256D) f:\dd\vctools\crt\vcstartup\src\misc\guard_support.c
+BIG-NEXT: Mod 0011 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\loadcfg.obj`:
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: Mod 0012 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_dtor.obj`:
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: EE3858E06B118BDBAAE53F5E55B0BB0C) f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_dtor.c
+BIG-NEXT: Mod 0013 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\dyn_tls_init.obj`:
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: 9DA48F59075BBAAAB4F7FC4575F34405) f:\dd\vctools\crt\vcstartup\src\utility\dyn_tls_init.c
+BIG-NEXT: Mod 0014 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr_detection.obj`:
+BIG-NEXT: - (MD5: 2DF28D8BA8B7AAAA67C94719B214B060) f:\dd\vctools\crt\vcstartup\src\utility\matherr_detection.c
+BIG-NEXT: Mod 0015 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_detection.obj`:
+BIG-NEXT: - (MD5: 737902C62D7458629D0DDD52E122C033) f:\dd\vctools\crt\vcstartup\src\utility\ucrt_detection.c
+BIG-NEXT: Mod 0016 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\argv_mode.obj`:
+BIG-NEXT: - (MD5: 634D3D57BDE292817F77F8DBF366E2D2) f:\dd\vctools\crt\vcstartup\src\defaults\argv_mode.cpp
+BIG-NEXT: Mod 0017 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\commit_mode.obj`:
+BIG-NEXT: - (MD5: CF5B0F6243121A3F5E206E07CA457128) f:\dd\vctools\crt\vcstartup\src\defaults\commit_mode.cpp
+BIG-NEXT: Mod 0018 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_local_stdio_options.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: E6391682D136711F96E730F4D6162E0C) f:\dd\vctools\crt\vcstartup\src\defaults\default_local_stdio_options.cpp
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2D5E699DF1BED89FCCCCCF0DCFC49050) f:\dd\externalapis\unifiedcrt\inc\stdio.h
+BIG-NEXT: - (MD5: 2443DB19DCC585E308F60DAFEF1D4C4C) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h
+BIG-NEXT: - (MD5: 79921ECB03C5C56E28D771ADF8910FD8) f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h
+BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: 303C50A7BC924CD426BAA20C7F16192C) f:\dd\vctools\crt\vcruntime\inc\vadefs.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: Mod 0019 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\denormal_control.obj`:
+BIG-NEXT: - (MD5: 0513001DBCB8CB8F8561DC117FD943BA) f:\dd\vctools\crt\vcstartup\src\defaults\denormal_control.cpp
+BIG-NEXT: Mod 0020 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\env_mode.obj`:
+BIG-NEXT: - (MD5: 5B7121FC3210A120D7B70CB668D8EF0C) f:\dd\vctools\crt\vcstartup\src\defaults\env_mode.cpp
+BIG-NEXT: Mod 0021 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\file_mode.obj`:
+BIG-NEXT: - (MD5: 749603C05EB2FB5024819A3107DA9A7D) f:\dd\vctools\crt\vcstartup\src\defaults\file_mode.cpp
+BIG-NEXT: Mod 0022 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\invalid_parameter_handler.obj`:
+BIG-NEXT: - (MD5: 0C385FD7C6DB91E0BA7C72C1AB680BE6) f:\dd\vctools\crt\vcstartup\src\defaults\invalid_parameter_handler.cpp
+BIG-NEXT: Mod 0023 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\matherr.obj`:
+BIG-NEXT: - (MD5: F8B3DAD79F14E4169CCBA611203C89CD) f:\dd\vctools\crt\vcstartup\src\defaults\matherr.cpp
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: Mod 0024 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\new_mode.obj`:
+BIG-NEXT: - (MD5: 4F22B6A5E4E0D01E8C000B17F2B2640D) f:\dd\vctools\crt\vcstartup\src\defaults\new_mode.cpp
+BIG-NEXT: Mod 0025 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\thread_locale.obj`:
+BIG-NEXT: - (MD5: 435F5F51541F7D6565DF6BE20F8AC8A3) f:\dd\vctools\crt\vcstartup\src\defaults\thread_locale.cpp
+BIG-NEXT: Mod 0026 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\tncleanup.obj`:
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 984A18787250F7F6D0506E6BC1FD7991) f:\dd\vctools\crt\vcstartup\src\eh\tncleanup.cpp
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 2465A06B1F50CD26AD5EC7D20DA6DB3D) f:\dd\vctools\crt\vcruntime\inc\vcruntime_typeinfo.h
+BIG-NEXT: - (MD5: 385CF08DA92F72075026067CE03F8402) f:\dd\vctools\crt\vcruntime\inc\vcruntime_exception.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: Mod 0027 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\exe_main.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: B71A807A307A52C400179EF5D3FAA1A7) f:\dd\vctools\crt\vcstartup\src\startup\exe_main.cpp
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: - (MD5: 2D5E699DF1BED89FCCCCCF0DCFC49050) f:\dd\externalapis\unifiedcrt\inc\stdio.h
+BIG-NEXT: - (MD5: 2443DB19DCC585E308F60DAFEF1D4C4C) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstdio.h
+BIG-NEXT: - (MD5: 79921ECB03C5C56E28D771ADF8910FD8) f:\dd\externalapis\unifiedcrt\inc\corecrt_stdio_config.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 36A3069CD09EC9F92668000F200D5545) f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl
+BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: 303C50A7BC924CD426BAA20C7F16192C) f:\dd\vctools\crt\vcruntime\inc\vadefs.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: Mod 0028 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\initializers.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: 8A16383C445FDABF21BDBAC3825E8133) f:\dd\externalapis\windows\8.1\sdk\inc\evntprov.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: Mod 0029 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: 2D42DDF1AAE9B3491E4BB346255346D5) f:\dd\vctools\crt\vcstartup\src\utility\utility.cpp
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: Mod 0030 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\ucrt_stubs.obj`:
+BIG-NEXT: - (MD5: 20976B3B6CD70F2DF77312D18D9C8D32) f:\dd\vctools\crt\vcstartup\src\utility\ucrt_stubs.cpp
+BIG-NEXT: Mod 0031 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\utility_desktop.obj`:
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: CC9AAE4BAA114C08FFC7F1515EC09E4C) f:\dd\vctools\crt\vcstartup\src\utility\utility_desktop.cpp
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: Mod 0032 | `f:\dd\vctools\crt\vcstartup\build\md\msvcrt_kernel32\obj1r\i386\default_precision.obj`:
+BIG-NEXT: - (MD5: 377E41F4DAE6F93EA819B4EFCF229F08) f:\dd\externalapis\unifiedcrt\inc\string.h
+BIG-NEXT: - (MD5: 96C01EE8E4C01B90601D93353838EBF8) f:\dd\externalapis\unifiedcrt\inc\corecrt_memory.h
+BIG-NEXT: - (MD5: A5976652B404EDDDBDA326FF9A9488A3) f:\dd\externalapis\unifiedcrt\inc\corecrt_memcpy_s.h
+BIG-NEXT: - (MD5: 9621B7E7C6A138B5185711F98CCC568E) f:\dd\vctools\crt\vcstartup\src\defaults\default_precision.cpp
+BIG-NEXT: - (MD5: 9393435BC7FDE9F624E309D56629171A) f:\dd\vctools\crt\vcruntime\inc\internal_shared.h
+BIG-NEXT: - (MD5: A40485987BE01BAF5F57569A41DAB837) f:\dd\vctools\crt\vcruntime\inc\vcruntime_new.h
+BIG-NEXT: - (MD5: F9FC1E83CBE1A51209ED1C05BB0F70B2) f:\dd\externalapis\windows\8.1\sdk\inc\winuser.h
+BIG-NEXT: - (MD5: 928553F8BA198C9030B65FA10B6B3DD2) f:\dd\externalapis\unifiedcrt\inc\malloc.h
+BIG-NEXT: - (MD5: 493F2CAB7A6BE4175748A9FC6C4A38FB) f:\dd\externalapis\windows\8.1\sdk\inc\basetsd.h
+BIG-NEXT: - (MD5: E4963431577926D9BA190CD6C10F8743) f:\dd\vctools\crt\vcruntime\inc\i386\xmmintrin.h
+BIG-NEXT: - (MD5: C3412F163DF064CCDEF8CFBE0A387550) f:\dd\externalapis\windows\8.1\sdk\inc\winbase.h
+BIG-NEXT: - (MD5: 7C388EF80868D8301B5A908485637FEE) f:\dd\vctools\crt\vcstartup\inc\vcstartup_internal.h
+BIG-NEXT: - (MD5: 23CC88BD1D9451C2CE5F824306E16E4D) f:\dd\externalapis\unifiedcrt\inc\math.h
+BIG-NEXT: - (MD5: C44C7E39EE3B3A4EF6B3211EC0110AA8) f:\dd\externalapis\unifiedcrt\inc\stdlib.h
+BIG-NEXT: - (MD5: DCC558DEFD73C17745F94CC5A98632D9) f:\dd\externalapis\windows\8.1\sdk\inc\stralign.h
+BIG-NEXT: - (MD5: ADDFD8BEB612E9A30D5FB7C44F9F3D37) f:\dd\externalapis\windows\8.1\sdk\inc\winnt.h
+BIG-NEXT: - (MD5: 386A22AB644E999820C7C22FCE5DB574) f:\dd\externalapis\unifiedcrt\inc\ctype.h
+BIG-NEXT: - (MD5: CA7D066706A198EA5999B084AAB0CE58) f:\dd\externalapis\windows\8.1\sdk\inc\guiddef.h
+BIG-NEXT: - (MD5: 2D923CBDE24BB8F217FE09A5F7D88929) f:\dd\externalapis\unifiedcrt\inc\corecrt_wstring.h
+BIG-NEXT: - (MD5: B38ACA278420B7C5F25A50AD159CACA0) f:\dd\externalapis\windows\8.1\sdk\inc\winerror.h
+BIG-NEXT: Mod 0033 | `Import:KERNEL32.dll`:
+BIG-NEXT: Mod 0034 | `KERNEL32.dll`:
+BIG-NEXT: Mod 0035 | `Import:VCRUNTIME140.dll`:
+BIG-NEXT: Mod 0036 | `VCRUNTIME140.dll`:
+BIG-NEXT: Mod 0037 | `Import:api-ms-win-crt-stdio-l1-1-0.dll`:
+BIG-NEXT: Mod 0038 | `api-ms-win-crt-stdio-l1-1-0.dll`:
+BIG-NEXT: Mod 0039 | `Import:api-ms-win-crt-runtime-l1-1-0.dll`:
+BIG-NEXT: Mod 0040 | `api-ms-win-crt-runtime-l1-1-0.dll`:
+BIG-NEXT: Mod 0041 | `Import:api-ms-win-crt-math-l1-1-0.dll`:
+BIG-NEXT: Mod 0042 | `api-ms-win-crt-math-l1-1-0.dll`:
+BIG-NEXT: Mod 0043 | `Import:api-ms-win-crt-locale-l1-1-0.dll`:
+BIG-NEXT: Mod 0044 | `api-ms-win-crt-locale-l1-1-0.dll`:
+BIG-NEXT: Mod 0045 | `Import:api-ms-win-crt-heap-l1-1-0.dll`:
+BIG-NEXT: Mod 0046 | `api-ms-win-crt-heap-l1-1-0.dll`:
+BIG-NEXT: Mod 0047 | `* Linker *`:
+
+BAD-BLOCK-SIZE: Native PDB Error: The PDB file is corrupt. Does not contain superblock
diff --git a/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test b/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test
index 2639490f542a..f25e9024453b 100644
--- a/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test
+++ b/test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test
@@ -1,65 +1,51 @@
; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-and-types-1.yaml
; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-and-types-2.yaml
; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
-; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s
-; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=INTMAIN %s
-; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=VOIDMAIN %s
-; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s
-; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-NAMES %s
-; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=IPI-UDT %s
+; RUN: llvm-pdbutil raw -types %t.3.pdb | FileCheck -check-prefix=TPI-TYPES %s
+; RUN: llvm-pdbutil raw -ids %t.3.pdb | FileCheck -check-prefix=IPI-TYPES %s
-TPI-TYPES: Type Info Stream (TPI)
-TPI-TYPES: Record count: 9
-TPI-TYPES-DAG: TypeLeafKind: LF_POINTER
-TPI-TYPES-DAG: TypeLeafKind: LF_FIELDLIST
-TPI-TYPES-DAG: TypeLeafKind: LF_ARGLIST
-TPI-TYPES-DAG: TypeLeafKind: LF_STRUCTURE
-TPI-TYPES-DAG: TypeLeafKind: LF_MEMBER
-TPI-TYPES-DAG: TypeLeafKind: LF_POINTER
-TPI-TYPES-DAG: TypeLeafKind: LF_ARGLIST
-TPI-TYPES-DAG: TypeLeafKind: LF_MFUNCTION
-TPI-TYPES-DAG: TypeLeafKind: LF_PROCEDURE
-TPI-TYPES-DAG: TypeLeafKind: LF_PROCEDURE
-TPI-TYPES-DAG: TypeLeafKind: LF_ARGLIST
+TPI-TYPES: Types (TPI Stream)
+TPI-TYPES-NEXT: ============================================================
+TPI-TYPES-NEXT: Showing 9 records
+TPI-TYPES-NEXT: 0x1000 | LF_POINTER [size = 12]
+TPI-TYPES-NEXT: referent = 0x0470 (char*), mode = pointer, opts = None, kind = ptr32
+TPI-TYPES-NEXT: 0x1001 | LF_FIELDLIST [size = 24]
+TPI-TYPES-NEXT: - LF_MEMBER [name = `FooMember`, Type = 0x0403 (void*), offset = 0, attrs = public]
+TPI-TYPES-NEXT: 0x1002 | LF_ARGLIST [size = 16]
+TPI-TYPES-NEXT: 0x0074 (int): `int`
+TPI-TYPES-NEXT: 0x1000: `char**`
+TPI-TYPES-NEXT: 0x1003 | LF_STRUCTURE [size = 36]
+TPI-TYPES-NEXT: class name: `FooBar`
+TPI-TYPES-NEXT: unique name: `FooBar`
+TPI-TYPES-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1001
+TPI-TYPES-NEXT: options: has unique name
+TPI-TYPES-NEXT: 0x1004 | LF_POINTER [size = 12]
+TPI-TYPES-NEXT: referent = 0x1003, mode = pointer, opts = None, kind = ptr32
+TPI-TYPES-NEXT: 0x1005 | LF_ARGLIST [size = 12]
+TPI-TYPES-NEXT: 0x0074 (int): `int`
+TPI-TYPES-NEXT: 0x1006 | LF_MFUNCTION [size = 28]
+TPI-TYPES-NEXT: return type = 1, # args = 0x1005, param list = 0x0003 (void)
+TPI-TYPES-NEXT: class type = 0x1003, this type = 0x1004, this adjust = 0
+TPI-TYPES-NEXT: calling conv = thiscall, options = constructor
+TPI-TYPES-NEXT: 0x1007 | LF_PROCEDURE [size = 16]
+TPI-TYPES-NEXT: return type = 0x0074 (int), # args = 2, param list = 0x1002
+TPI-TYPES-NEXT: calling conv = cdecl, options = None
+TPI-TYPES-NEXT: 0x1008 | LF_PROCEDURE [size = 16]
+TPI-TYPES-NEXT: return type = 0x0003 (void), # args = 2, param list = 0x1002
+TPI-TYPES-NEXT: calling conv = cdecl, options = None
-; Both procedures should use the same arglist even though they have a different
-; return type.
-INTMAIN: ArgList ([[ID:.*]])
-INTMAIN-NEXT: TypeLeafKind: LF_ARGLIST
-INTMAIN-NEXT: NumArgs: 2
-INTMAIN-NEXT: Arguments [
-INTMAIN-NEXT: ArgType: int
-INTMAIN-NEXT: ArgType: char**
-INTMAIN: TypeLeafKind: LF_PROCEDURE
-INTMAIN: ReturnType: int
-INTMAIN: NumParameters: 2
-INTMAIN-NEXT: ArgListType: (int, char**) ([[ID]])
-
-VOIDMAIN: ArgList ([[ID:.*]])
-VOIDMAIN-NEXT: TypeLeafKind: LF_ARGLIST
-VOIDMAIN-NEXT: NumArgs: 2
-VOIDMAIN-NEXT: Arguments [
-VOIDMAIN-NEXT: ArgType: int
-VOIDMAIN-NEXT: ArgType: char**
-VOIDMAIN: TypeLeafKind: LF_PROCEDURE
-VOIDMAIN: ReturnType: void
-VOIDMAIN: NumParameters: 2
-VOIDMAIN-NEXT: ArgListType: (int, char**) ([[ID]])
-
-IPI-TYPES: Type Info Stream (IPI)
-IPI-TYPES: Record count: 6
-IPI-TYPES-DAG: TypeLeafKind: LF_FUNC_ID
-IPI-TYPES-DAG: TypeLeafKind: LF_MFUNC_ID
-IPI-TYPES-DAG: TypeLeafKind: LF_UDT_MOD_SRC_LINE
-IPI-TYPES-DAG: TypeLeafKind: LF_FUNC_ID
-IPI-TYPES-DAG: TypeLeafKind: LF_FUNC_ID
-IPI-TYPES-DAG: TypeLeafKind: LF_MFUNC_ID
-
-IPI-NAMES-DAG: Name: main
-IPI-NAMES-DAG: Name: FooMethod
-IPI-NAMES-DAG: Name: main2
-IPI-NAMES-DAG: Name: foo
-IPI-NAMES-DAG: Name: FooMethod2
-
-IPI-UDT: TypeLeafKind: LF_UDT_MOD_SRC_LINE
-IPI-UDT-NEXT: UDT: FooBar
+IPI-TYPES: Types (IPI Stream)
+IPI-TYPES-NEXT: ============================================================
+IPI-TYPES-NEXT: Showing 6 records
+IPI-TYPES-NEXT: 0x1000 | LF_FUNC_ID [size = 20]
+IPI-TYPES-NEXT: name = main, type = 0x1007, parent scope = <no type>
+IPI-TYPES-NEXT: 0x1001 | LF_MFUNC_ID [size = 24]
+IPI-TYPES-NEXT: name = FooMethod, type = 0x1006, class type = 0x1003
+IPI-TYPES-NEXT: 0x1002 | LF_UDT_MOD_SRC_LINE [size = 20]
+IPI-TYPES-NEXT: udt = 0x1003, mod = 0, file = 0, line = 0
+IPI-TYPES-NEXT: 0x1003 | LF_FUNC_ID [size = 20]
+IPI-TYPES-NEXT: name = main2, type = 0x1007, parent scope = <no type>
+IPI-TYPES-NEXT: 0x1004 | LF_FUNC_ID [size = 16]
+IPI-TYPES-NEXT: name = foo, type = 0x1008, parent scope = <no type>
+IPI-TYPES-NEXT: 0x1005 | LF_MFUNC_ID [size = 24]
+IPI-TYPES-NEXT: name = FooMethod2, type = 0x1006, class type = 0x1003
diff --git a/test/DebugInfo/PDB/pdbdump-mergeids.test b/test/DebugInfo/PDB/pdbdump-mergeids.test
index 1c0a8704af2a..441ce4d8dbc8 100644
--- a/test/DebugInfo/PDB/pdbdump-mergeids.test
+++ b/test/DebugInfo/PDB/pdbdump-mergeids.test
@@ -1,31 +1,24 @@
; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-ids-1.yaml
; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-ids-2.yaml
; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
-; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
-; RUN: llvm-pdbutil raw -ipi-records %t.3.pdb | FileCheck -check-prefix=SUBSTRS %s
-; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s
+; RUN: llvm-pdbutil raw -ids %t.3.pdb | FileCheck -check-prefix=MERGED %s
+; RUN: llvm-pdbutil raw -types %t.3.pdb | FileCheck -check-prefix=TPI-EMPTY %s
-MERGED: Type Info Stream (IPI)
-MERGED: Record count: 8
-MERGED-DAG: StringData: One
-MERGED-DAG: StringData: Two
-MERGED-DAG: StringData: SubOne
-MERGED-DAG: StringData: SubTwo
-MERGED-DAG: StringData: Main
-MERGED-DAG: TypeLeafKind: LF_SUBSTR_LIST
-MERGED-DAG: StringData: OnlyInFirst
-MERGED-DAG: StringData: OnlyInSecond
+MERGED: Types (IPI Stream)
+MERGED-NEXT: ============================================================
+MERGED-NEXT: Showing 8 records
+MERGED-NEXT: 0x1000 | LF_STRING_ID [size = 12] ID: <no type>, String: One
+MERGED-NEXT: 0x1001 | LF_STRING_ID [size = 12] ID: <no type>, String: Two
+MERGED-NEXT: 0x1002 | LF_STRING_ID [size = 20] ID: <no type>, String: OnlyInFirst
+MERGED-NEXT: 0x1003 | LF_STRING_ID [size = 16] ID: <no type>, String: SubOne
+MERGED-NEXT: 0x1004 | LF_STRING_ID [size = 16] ID: <no type>, String: SubTwo
+MERGED-NEXT: 0x1005 | LF_SUBSTR_LIST [size = 16]
+MERGED-NEXT: 0x1003: `SubOne`
+MERGED-NEXT: 0x1004: `SubTwo`
+MERGED-NEXT: 0x1006 | LF_STRING_ID [size = 16] ID: 0x1005, String: Main
+MERGED-NEXT: 0x1007 | LF_STRING_ID [size = 24] ID: <no type>, String: OnlyInSecond
-SUBSTRS: StringList
-SUBSTRS: TypeLeafKind: LF_SUBSTR_LIST
-SUBSTRS-NEXT: NumStrings: 2
-SUBSTRS-NEXT: Strings [
-SUBSTRS-NEXT: SubOne
-SUBSTRS-NEXT: SubTwo
-SUBSTRS: StringId
-SUBSTRS-NEXT: TypeLeafKind: LF_STRING_ID
-SUBSTRS-NEXT: Id: "SubOne" "SubTwo"
-SUBSTRS-NEXT: StringData: Main
-
-TPI-EMPTY: Record count: 0
+TPI-EMPTY: Types (TPI Stream)
+TPI-EMPTY-NEXT: ============================================================
+TPI-EMPTY-NEXT: Showing 0 records
diff --git a/test/DebugInfo/PDB/pdbdump-mergetypes.test b/test/DebugInfo/PDB/pdbdump-mergetypes.test
index 8d32b4d176f2..9aae40543697 100644
--- a/test/DebugInfo/PDB/pdbdump-mergetypes.test
+++ b/test/DebugInfo/PDB/pdbdump-mergetypes.test
@@ -1,24 +1,36 @@
-; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml
-; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml
-; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
-; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=MERGED %s
-; RUN: llvm-pdbutil raw -tpi-records %t.3.pdb | FileCheck -check-prefix=ARGLIST %s
-
-
-MERGED: Type Info Stream (TPI)
-MERGED: Record count: 9
-MERGED-DAG: PointeeType: unsigned
-MERGED-DAG: PointeeType: unsigned*
-MERGED-DAG: PointeeType: unsigned**
-MERGED-DAG: PointeeType: __int64
-MERGED-DAG: PointeeType: __int64*
-MERGED-DAG: Name: OnlyInMerge1
-MERGED-DAG: Name: OnlyInMerge2
-MERGED-DAG: TypeLeafKind: LF_ARGLIST
-
-ARGLIST: TypeLeafKind: LF_ARGLIST
-ARGLIST-NEXT: NumArgs: 3
-ARGLIST-NEXT: Arguments [
-ARGLIST-NEXT: ArgType: unsigned
-ARGLIST-NEXT: ArgType: unsigned*
-ARGLIST-NEXT: ArgType: unsigned**
++; RUN: llvm-pdbutil yaml2pdb -pdb=%t.1.pdb %p/Inputs/merge-types-1.yaml
+; RUN: llvm-pdbutil yaml2pdb -pdb=%t.2.pdb %p/Inputs/merge-types-2.yaml
+; RUN: llvm-pdbutil merge -pdb=%t.3.pdb %t.1.pdb %t.2.pdb
+; RUN: llvm-pdbutil raw -types %t.3.pdb | FileCheck -check-prefix=MERGED %s
+
+
+MERGED: Types (TPI Stream)
+MERGED-NEXT: ============================================================
+MERGED-NEXT: Showing 9 records
+MERGED-NEXT: 0x1000 | LF_POINTER [size = 12]
+MERGED-NEXT: referent = 0x0075 (unsigned), mode = pointer, opts = None, kind = ptr32
+MERGED-NEXT: 0x1001 | LF_POINTER [size = 12]
+MERGED-NEXT: referent = 0x0076 (__int64), mode = pointer, opts = None, kind = ptr32
+MERGED-NEXT: 0x1002 | LF_STRUCTURE [size = 48]
+MERGED-NEXT: class name: `OnlyInMerge1`
+MERGED-NEXT: unique name: `OnlyInMerge1`
+MERGED-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+MERGED-NEXT: options: forward ref | has unique name
+MERGED-NEXT: 0x1003 | LF_POINTER [size = 12]
+MERGED-NEXT: referent = 0x1000, mode = pointer, opts = None, kind = ptr32
+MERGED-NEXT: 0x1004 | LF_POINTER [size = 12]
+MERGED-NEXT: referent = 0x1003, mode = pointer, opts = None, kind = ptr32
+MERGED-NEXT: 0x1005 | LF_POINTER [size = 12]
+MERGED-NEXT: referent = 0x1001, mode = pointer, opts = None, kind = ptr32
+MERGED-NEXT: 0x1006 | LF_ARGLIST [size = 20]
+MERGED-NEXT: 0x0075 (unsigned): `unsigned`
+MERGED-NEXT: 0x1000: `unsigned*`
+MERGED-NEXT: 0x1003: `unsigned**`
+MERGED-NEXT: 0x1007 | LF_PROCEDURE [size = 16]
+MERGED-NEXT: return type = 0x0075 (unsigned), # args = 0, param list = 0x1006
+MERGED-NEXT: calling conv = cdecl, options = None
+MERGED-NEXT: 0x1008 | LF_STRUCTURE [size = 48]
+MERGED-NEXT: class name: `OnlyInMerge2`
+MERGED-NEXT: unique name: `OnlyInMerge2`
+MERGED-NEXT: vtable: <no type>, base list: <no type>, field list: <no type>
+MERGED-NEXT: options: forward ref | has unique name
diff --git a/test/DebugInfo/PDB/pdbdump-raw-blocks.test b/test/DebugInfo/PDB/pdbdump-raw-blocks.test
index 14e1f86fc029..b695d5a1c4cd 100644
--- a/test/DebugInfo/PDB/pdbdump-raw-blocks.test
+++ b/test/DebugInfo/PDB/pdbdump-raw-blocks.test
@@ -1,35 +1,29 @@
-; RUN: llvm-pdbutil raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
-; RUN: llvm-pdbutil raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
-; RUN: not llvm-pdbutil raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
-; RUN: not llvm-pdbutil raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
-; RUN: not llvm-pdbutil raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
-
-BLOCK0: Block Data {
-BLOCK0-NEXT: Block 0 (
-BLOCK0-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 |Microsoft C/C++ |
-BLOCK0-NEXT: 0010: 4D534620 372E3030 0D0A1A44 53000000 |MSF 7.00...DS...|
-BLOCK0-NEXT: 0020: 00100000 02000000 19000000 88000000 |................|
-BLOCK0-NEXT: 0030: 00000000 18000000 00000000 00000000 |................|
-BLOCK0: 0FE0: 00000000 00000000 00000000 00000000 |................|
-BLOCK0-NEXT: 0FF0: 00000000 00000000 00000000 00000000 |................|
-BLOCK0-NEXT: )
-BLOCK0-NEXT: }
-
-BLOCK01: Block Data {
-BLOCK01-NEXT: Block 0 (
-BLOCK01-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 |Microsoft C/C++ |
-BLOCK01-NEXT: 0010: 4D534620 372E3030 0D0A1A44 53000000 |MSF 7.00...DS...|
-BLOCK01-NEXT: 0020: 00100000 02000000 19000000 88000000 |................|
-BLOCK01-NEXT: 0030: 00000000 18000000 00000000 00000000 |................|
-BLOCK01: 0FE0: 00000000 00000000 00000000 00000000 |................|
-BLOCK01-NEXT: 0FF0: 00000000 00000000 00000000 00000000 |................|
-BLOCK01-NEXT: )
-BLOCK01-NEXT: Block 1 (
-BLOCK01-NEXT: 0000: C0FCFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
-BLOCK01-NEXT: 0010: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
-BLOCK01: 0FE0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
-BLOCK01-NEXT: 0FF0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
-BLOCK01-NEXT: )
-BLOCK01-NEXT: }
-
-BADSYNTAX: Argument '{{.*}}' invalid format.
+; RUN: llvm-pdbutil raw -block-data=0 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK0 %s
+; RUN: llvm-pdbutil raw -block-data=0-1 %p/Inputs/empty.pdb | FileCheck --check-prefix=BLOCK01 %s
+; RUN: not llvm-pdbutil raw -block-data=0,1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
+; RUN: not llvm-pdbutil raw -block-data=0a1 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
+; RUN: not llvm-pdbutil raw -block-data=0- %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BADSYNTAX %s
+
+BLOCK0: MSF Blocks
+BLOCK0-NEXT: ============================================================
+BLOCK0-NEXT: Block 0 (
+BLOCK0-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 4D534620 372E3030 0D0A1A44 53000000 |Microsoft C/C++ MSF 7.00...DS...|
+BLOCK0-NEXT: 0020: 00100000 02000000 19000000 88000000 00000000 18000000 00000000 00000000 |................................|
+BLOCK0-NEXT: 0040: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................|
+BLOCK0-NEXT: 0060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................|
+BLOCK0-NOT: Block 1 (
+
+BLOCK01: MSF Blocks
+BLOCK01-NEXT: ============================================================
+BLOCK01-NEXT: Block 0 (
+BLOCK01-NEXT: 0000: 4D696372 6F736F66 7420432F 432B2B20 4D534620 372E3030 0D0A1A44 53000000 |Microsoft C/C++ MSF 7.00...DS...|
+BLOCK01-NEXT: 0020: 00100000 02000000 19000000 88000000 00000000 18000000 00000000 00000000 |................................|
+BLOCK01-NEXT: 0040: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................|
+BLOCK01-NEXT: 0060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................|
+BLOCK01: Block 1 (
+BLOCK01-NEXT: 0000: C0FCFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................|
+BLOCK01-NEXT: 0020: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................|
+BLOCK01-NEXT: 0040: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................................|
+BLOCK01-NOT: Block 2 (
+
+BADSYNTAX: Argument '{{.*}}' invalid format.
diff --git a/test/DebugInfo/PDB/pdbdump-raw-stream.test b/test/DebugInfo/PDB/pdbdump-raw-stream.test
index 846960a0964a..2f8e05ad0583 100644
--- a/test/DebugInfo/PDB/pdbdump-raw-stream.test
+++ b/test/DebugInfo/PDB/pdbdump-raw-stream.test
@@ -1,23 +1,28 @@
-; RUN: llvm-pdbutil raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM1 %s
-; RUN: not llvm-pdbutil raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
-
-STREAM1: Stream Data {
-STREAM1-NEXT: Stream {
-STREAM1-NEXT: Index: 1
-STREAM1-NEXT: Type: PDB Stream
-STREAM1-NEXT: Size: 118
-STREAM1-NEXT: Blocks: [19]
-STREAM1-NEXT: Data (
-STREAM1-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 |..1....T.....5VA|
-STREAM1-NEXT: 0010: 86A0A249 896F9988 FAE52FF0 22000000 |...I.o..../."...|
-STREAM1-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 |/LinkInfo./names|
-STREAM1-NEXT: 0030: 002F7372 632F6865 61646572 626C6F63 |./src/headerbloc|
-STREAM1-NEXT: 0040: 6B000300 00000600 00000100 00001A00 |k...............|
-STREAM1-NEXT: 0050: 00000000 00001100 00000900 00000A00 |................|
-STREAM1-NEXT: 0060: 00000D00 00000000 00000500 00000000 |................|
-STREAM1-NEXT: 0070: 00004191 3201 |..A.2.|
-STREAM1-NEXT: )
-STREAM1-NEXT: }
-STREAM1-NEXT: }
-
-INVALIDSTREAM: Native PDB Error: The specified stream could not be loaded.
+; RUN: llvm-pdbutil raw -stream-data=1 %p/Inputs/empty.pdb | FileCheck --check-prefix=STREAM %s
+; RUN: llvm-pdbutil raw -stream-data=100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=INVALIDSTREAM %s
+; RUN: llvm-pdbutil raw -stream-data=1,100 %p/Inputs/empty.pdb 2>&1 | FileCheck --check-prefix=BOTH %s
+
+STREAM: Stream Data
+STREAM-NEXT: ============================================================
+STREAM-NEXT: Stream 1 (118 bytes): PDB Stream
+STREAM-NEXT: Data (
+STREAM-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...|
+STREAM-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc|
+STREAM-NEXT: 0040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................|
+STREAM-NEXT: 0060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.|
+STREAM-NEXT: )
+
+INVALIDSTREAM: Stream Data
+INVALIDSTREAM-NEXT: ============================================================
+INVALIDSTREAM-NEXT: Stream 100: Not present
+
+BOTH: Stream Data
+BOTH-NEXT: ============================================================
+BOTH-NEXT: Stream 1 (118 bytes): PDB Stream
+BOTH-NEXT: Data (
+BOTH-NEXT: 0000: 942E3101 E207E554 01000000 0B355641 86A0A249 896F9988 FAE52FF0 22000000 |..1....T.....5VA...I.o..../."...|
+BOTH-NEXT: 0020: 2F4C696E 6B496E66 6F002F6E 616D6573 002F7372 632F6865 61646572 626C6F63 |/LinkInfo./names./src/headerbloc|
+BOTH-NEXT: 0040: 6B000300 00000600 00000100 00001A00 00000000 00001100 00000900 00000A00 |k...............................|
+BOTH-NEXT: 0060: 00000D00 00000000 00000500 00000000 00004191 3201 |..................A.2.|
+BOTH-NEXT: )
+BOTH-NEXT: Stream 100: Not present
diff --git a/test/DebugInfo/PDB/pdbdump-readwrite.test b/test/DebugInfo/PDB/pdbdump-readwrite.test
index ee53f3b4cd2a..51ebd754545f 100644
--- a/test/DebugInfo/PDB/pdbdump-readwrite.test
+++ b/test/DebugInfo/PDB/pdbdump-readwrite.test
@@ -3,48 +3,33 @@ RUN: -pdb-stream -string-table -tpi-stream -stream-directory \
RUN: -stream-metadata %p/Inputs/empty.pdb > %t.1
RUN: llvm-pdbutil yaml2pdb -pdb=%t.2 %t.1
-RUN: llvm-pdbutil raw -headers -string-table -tpi-records %p/Inputs/empty.pdb | FileCheck %s
-RUN: llvm-pdbutil raw -headers -string-table -tpi-records %t.2 | FileCheck %s
+RUN: llvm-pdbutil raw -summary -string-table -types %p/Inputs/empty.pdb | FileCheck %s
+RUN: llvm-pdbutil raw -summary -string-table -types %t.2 | FileCheck %s
-CHECK: FileHeaders {
-CHECK-NEXT: BlockSize: 4096
-CHECK-NEXT: FreeBlockMap:
-CHECK-NEXT: NumBlocks:
-CHECK-NEXT: NumDirectoryBytes:
-CHECK-NEXT: Unknown1: 0
-CHECK-NEXT: BlockMapAddr:
-CHECK-NEXT: NumDirectoryBlocks: 1
-CHECK-NEXT: DirectoryBlocks:
-CHECK-NEXT: NumStreams:
-CHECK-NEXT: }
-CHECK: String Table {
-CHECK-DAG: 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)'
-CHECK-DAG: 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
-CHECK-DAG: '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = '
-CHECK-NEXT: }
-CHECK: PDB Stream {
-CHECK-NEXT: Version: 20000404
-CHECK-NEXT: Signature: 0x54E507E2
-CHECK-NEXT: Age: 1
-CHECK-NEXT: Guid: {0B355641-86A0-A249-896F-9988FAE52FF0}
-CHECK-NEXT: Features: 0x1
-CHECK-NEXT: Named Streams {
-CHECK: /names:
-CHECK: }
-CHECK-NEXT: }
-CHECK: Type Info Stream (TPI) {
-CHECK-NEXT: TPI Version: 20040203
-CHECK-NEXT: Record count: 75
-CHECK: DBI Stream {
-CHECK-NEXT: Dbi Version: 19990903
-CHECK-NEXT: Age: 1
-CHECK-NEXT: Incremental Linking: Yes
-CHECK-NEXT: Has CTypes: No
-CHECK-NEXT: Is Stripped: No
-CHECK-NEXT: Machine Type: x86
-CHECK-NEXT: Symbol Record Stream Index:
-CHECK-NEXT: Public Symbol Stream Index:
-CHECK-NEXT: Global Symbol Stream Index:
-CHECK-NEXT: Toolchain Version: 12.0
-CHECK-NEXT: mspdb120.dll version: 12.0.31101
-CHECK-NEXT: }
+
+CHECK: Summary
+CHECK-NEXT: ============================================================
+CHECK-NEXT: Block Size: 4096
+CHECK-NEXT: Number of blocks:
+CHECK-NEXT: Number of streams:
+CHECK-NEXT: Signature: 1424295906
+CHECK-NEXT: Age: 1
+CHECK-NEXT: GUID: {0B355641-86A0-A249-896F-9988FAE52FF0}
+CHECK-NEXT: Features: 0x1
+CHECK-NEXT: Has Debug Info: true
+CHECK-NEXT: Has Types: true
+CHECK-NEXT: Has IDs: true
+CHECK-NEXT: Has Globals:
+CHECK-NEXT: Has Publics:
+CHECK-NEXT: Is incrementally linked: true
+CHECK-NEXT: Has conflicting types: false
+CHECK-NEXT: Is stripped: false
+CHECK: String Table
+CHECK-NEXT: ============================================================
+CHECK-NEXT: ID | String
+CHECK-NEXT: {{.*}} | 'd:\src\llvm\test\debuginfo\pdb\inputs\predefined c++ attributes (compiler internal)'
+CHECK-NEXT: {{.*}} | 'd:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp'
+CHECK-NEXT: {{.*}} | '$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = '
+CHECK: Types (TPI Stream)
+CHECK-NEXT: ============================================================
+CHECK-NEXT: Showing 75 records
diff --git a/test/DebugInfo/X86/block-capture.ll b/test/DebugInfo/X86/block-capture.ll
index 168040507eef..14927eef59d4 100644
--- a/test/DebugInfo/X86/block-capture.ll
+++ b/test/DebugInfo/X86/block-capture.ll
@@ -123,7 +123,7 @@ attributes #3 = { nounwind }
!66 = !DILocation(line: 2, column: 20, scope: !8)
!67 = !DILocation(line: 2, column: 21, scope: !8)
!68 = !DILocalVariable(name: "block", line: 2, scope: !8, file: !5, type: !25)
-!69 = !DIExpression(DW_OP_deref, DW_OP_plus, 32)
+!69 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32)
!70 = !DILocation(line: 2, column: 9, scope: !8)
!71 = !DILocation(line: 2, column: 23, scope: !72)
!72 = distinct !DILexicalBlock(line: 2, column: 21, file: !1, scope: !8)
diff --git a/test/DebugInfo/X86/debug-info-block-captured-self.ll b/test/DebugInfo/X86/debug-info-block-captured-self.ll
index 1085eaef0d4e..e1620af50255 100644
--- a/test/DebugInfo/X86/debug-info-block-captured-self.ll
+++ b/test/DebugInfo/X86/debug-info-block-captured-self.ll
@@ -107,5 +107,5 @@ define internal void @"__24-[Main initWithContext:]_block_invoke_2"(i8* %.block_
!106 = !DILocation(line: 40, scope: !42)
!107 = !DIFile(filename: "llvm/tools/clang/test/CodeGenObjC/debug-info-block-captured-self.m", directory: "")
!108 = !{i32 1, !"Debug Info Version", i32 3}
-!109 = !DIExpression(DW_OP_plus, 32, DW_OP_deref)
-!110 = !DIExpression(DW_OP_plus, 32, DW_OP_deref)
+!109 = !DIExpression(DW_OP_plus_uconst, 32, DW_OP_deref)
+!110 = !DIExpression(DW_OP_plus_uconst, 32, DW_OP_deref)
diff --git a/test/DebugInfo/X86/debug-info-blocks.ll b/test/DebugInfo/X86/debug-info-blocks.ll
index 859eef804bb1..b79ad89be27d 100644
--- a/test/DebugInfo/X86/debug-info-blocks.ll
+++ b/test/DebugInfo/X86/debug-info-blocks.ll
@@ -380,4 +380,4 @@ attributes #3 = { nounwind }
!108 = !DILocation(line: 61, scope: !36)
!109 = !DILocation(line: 62, scope: !36)
!110 = !{i32 1, !"Debug Info Version", i32 3}
-!111 = !DIExpression(DW_OP_deref, DW_OP_plus, 32)
+!111 = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 32)
diff --git a/test/DebugInfo/X86/double-declare.ll b/test/DebugInfo/X86/double-declare.ll
new file mode 100644
index 000000000000..8ed4319b323a
--- /dev/null
+++ b/test/DebugInfo/X86/double-declare.ll
@@ -0,0 +1,44 @@
+; RUN: llc -mtriple=x86_64-apple-darwin -O0 -filetype=obj -o - < %s | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+; PR33157. Don't crash on duplicate dbg.declare.
+; CHECK: DW_TAG_formal_parameter
+; CHECK: DW_AT_location [DW_FORM_exprloc]
+; CHECK-NOT: DW_AT_location
+@g = external global i32
+@h = external global i32
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+define void @f(i32* byval %p, i1 %c) !dbg !5 {
+ br i1 %c, label %x, label %y
+
+x:
+ call void @llvm.dbg.declare(metadata i32* %p, metadata !10, metadata !DIExpression()), !dbg !12
+ store i32 42, i32* @g, !dbg !12
+ br label %done
+
+y:
+ call void @llvm.dbg.declare(metadata i32* %p, metadata !10, metadata !DIExpression()), !dbg !12
+ store i32 42, i32* @h, !dbg !12
+ br label %done
+
+done:
+ ret void
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!22, !23}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !1, producer: "clang version 5.0.0 ", isOptimized: true, runtimeVersion: 2, emissionKind: FullDebug)
+!1 = !DIFile(filename: "<stdin>", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
+!5 = distinct !DISubprogram(name: "f", isLocal: true, isDefinition: true, scopeLine: 37, flags: DIFlagPrototyped, isOptimized: true, unit: !0, type: !99, scope: !1)
+!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DILocalVariable(name: "aRect", arg: 1, scope: !11, file: !1, line: 38, type: !6)
+!11 = distinct !DILexicalBlock(scope: !98, file: !1, line: 38)
+!12 = !DILocation(line: 43, scope: !11, inlinedAt: !13)
+!13 = distinct !DILocation(line: 43, scope: !5)
+!22 = !{i32 2, !"Dwarf Version", i32 4}
+!23 = !{i32 2, !"Debug Info Version", i32 3}
+!62 = !{!10}
+!98 = distinct !DISubprogram(name: "NSMaxX", scope: !1, file: !1, line: 27, isLocal: true, isDefinition: true, scopeLine: 27, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !62, type: !99)
+!99 = !DISubroutineType(types: !100)
+!100 = !{null}
diff --git a/test/DebugInfo/X86/dw_op_minus.ll b/test/DebugInfo/X86/dw_op_minus.ll
index 8e65b489c27b..30bf58378005 100644
--- a/test/DebugInfo/X86/dw_op_minus.ll
+++ b/test/DebugInfo/X86/dw_op_minus.ll
@@ -10,7 +10,7 @@
; Capture(buf);
; }
; }
-; The interesting part is !DIExpression(DW_OP_minus, 400)
+; The interesting part is !DIExpression(DW_OP_constu, 400, DW_OP_minus)
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@@ -56,7 +56,7 @@ declare void @Capture(i32*)
!14 = !{i32 2, !"Debug Info Version", i32 3}
!15 = !{!"clang version 3.8.0 (trunk 248518) (llvm/trunk 248512)"}
!16 = !DILocation(line: 5, column: 3, scope: !4)
-!17 = !DIExpression(DW_OP_minus, 400)
+!17 = !DIExpression(DW_OP_constu, 400, DW_OP_minus)
!18 = !DILocation(line: 5, column: 7, scope: !4)
!19 = !DILocation(line: 6, column: 11, scope: !4)
!20 = !DILocation(line: 6, column: 3, scope: !4)
diff --git a/test/DebugInfo/X86/dw_op_minus_direct.ll b/test/DebugInfo/X86/dw_op_minus_direct.ll
index 8d346be532e8..69f4b2c3ef6a 100644
--- a/test/DebugInfo/X86/dw_op_minus_direct.ll
+++ b/test/DebugInfo/X86/dw_op_minus_direct.ll
@@ -51,7 +51,7 @@ attributes #1 = { nounwind readnone }
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{!12}
!12 = !DILocalVariable(name: "i", arg: 1, scope: !7, file: !1, line: 1, type: !10)
-!13 = !DIExpression(DW_OP_minus, 1, DW_OP_stack_value)
+!13 = !DIExpression(DW_OP_constu, 1, DW_OP_minus, DW_OP_stack_value)
!14 = !DILocation(line: 1, column: 13, scope: !7)
!15 = !DILocation(line: 2, column: 11, scope: !7)
!16 = !DILocation(line: 2, column: 3, scope: !7)
diff --git a/test/DebugInfo/X86/safestack-byval.ll b/test/DebugInfo/X86/safestack-byval.ll
index 42e94698818c..8742c90bc298 100644
--- a/test/DebugInfo/X86/safestack-byval.ll
+++ b/test/DebugInfo/X86/safestack-byval.ll
@@ -14,7 +14,7 @@
; }
; CHECK: ![[ZZZ:.*]] = !DILocalVariable(name: "zzz",
-; CHECK: ![[ZZZ_EXPR:.*]] = !DIExpression(DW_OP_deref, DW_OP_minus, 400)
+; CHECK: ![[ZZZ_EXPR:.*]] = !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus)
; CHECK: DBG_VALUE {{.*}} ![[ZZZ]], ![[ZZZ_EXPR]]
%struct.S = type { [100 x i32] }
@@ -79,7 +79,7 @@ attributes #2 = { argmemonly nounwind }
!20 = !{i32 2, !"Debug Info Version", i32 3}
!21 = !{!"clang version 3.8.0 (trunk 254107) (llvm/trunk 254109)"}
!22 = !DILocation(line: 8, column: 9, scope: !12)
-!23 = !DIExpression(DW_OP_deref, DW_OP_minus, 400)
+!23 = !DIExpression(DW_OP_deref, DW_OP_constu, 400, DW_OP_minus)
!24 = !DILocation(line: 8, column: 28, scope: !12)
!25 = !DIExpression()
!26 = !DILocation(line: 9, column: 10, scope: !12)
diff --git a/test/DebugInfo/X86/stack-value-dwarf2.ll b/test/DebugInfo/X86/stack-value-dwarf2.ll
index 61595f7861fe..b653784ec668 100644
--- a/test/DebugInfo/X86/stack-value-dwarf2.ll
+++ b/test/DebugInfo/X86/stack-value-dwarf2.ll
@@ -93,4 +93,4 @@ attributes #1 = { nounwind readnone }
!15 = !DISubprogram(name: "<(lambda at test.ii:87:58)>", scope: !0, file: !1, line: 27, type: !6, isLocal: false, isDefinition: false, scopeLine: 27, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true, templateParams: !2)
!16 = distinct !DILocation(line: 99, column: 21, scope: !17)
!17 = !DILexicalBlockFile(scope: !5, file: !1, discriminator: 2)
-!18 = !DIExpression(DW_OP_plus, 4, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 32)
+!18 = !DIExpression(DW_OP_plus_uconst, 4, DW_OP_stack_value, DW_OP_LLVM_fragment, 64, 32)
diff --git a/test/DebugInfo/X86/unattached-global.ll b/test/DebugInfo/X86/unattached-global.ll
index 5d4be7377ef4..5e9af695c8dc 100644
--- a/test/DebugInfo/X86/unattached-global.ll
+++ b/test/DebugInfo/X86/unattached-global.ll
@@ -12,7 +12,7 @@ target triple = "x86_64-unknown-linux-gnu"
!1 = !{!2}
!2 = !DIGlobalVariableExpression(var: !3, expr: !4)
!3 = distinct !DIGlobalVariable(name: "a", scope: null, isLocal: false, isDefinition: true, type: !6)
-!4 = !DIExpression(DW_OP_plus, 4)
+!4 = !DIExpression(DW_OP_plus_uconst, 4)
!5 = !DIFile(filename: "<stdin>", directory: "/")
!6 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
diff --git a/test/DebugInfo/dwarfdump-str-offsets-dwp.test b/test/DebugInfo/dwarfdump-str-offsets-dwp.test
new file mode 100644
index 000000000000..ceca3225f075
--- /dev/null
+++ b/test/DebugInfo/dwarfdump-str-offsets-dwp.test
@@ -0,0 +1,56 @@
+RUN: llvm-dwarfdump %p/Inputs/dwarfdump-str-offsets-dwp.x86_64.o | FileCheck %s
+
+; Verify that the correct strings from each unit are displayed and that the
+; index for the .debug_str_offsets section has the right values.
+
+; CHECK: Compile Unit
+; CHECK-NOT: NULL
+; CHECK: DW_TAG_compile_unit
+; CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer")
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_1")
+; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU1")
+; CHECK-NOT: NULL
+
+; CHECK: Compile Unit
+; CHECK-NOT: NULL
+; CHECK: DW_TAG_compile_unit
+; CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer")
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_2")
+; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008)
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU2")
+;
+; CHECK: Type Unit
+; CHECK-NOT: NULL
+; CHECK: DW_TAG_type_unit
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit_1")
+; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c)
+; CHECK-NOT: NULL
+; CHECK: DW_TAG_structure_type
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct_1")
+;
+; CHECK: Type Unit
+; CHECK-NOT: NULL
+; CHECK: DW_TAG_type_unit
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit_2")
+; CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c)
+; CHECK-NOT: NULL
+; CHECK: DW_TAG_structure_type
+; CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct_2")
+
+; Verify the correct offets of the compile and type units contributions in the
+; index tables.
+
+; CHECK: .debug_cu_index contents:
+; CHECK-NOT: contents:
+; CHECK: 1 0xddeeaaddbbaabbee [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}})
+; CHECK-SAME: [0x00000000
+; CHECK-NEXT: 2 0xff00ffeeffaaff00 [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}})
+; CHECK-SAME: [0x00000024
+
+; CHECK: .debug_tu_index contents:
+; CHECK-NOT: contents:
+; CHECK: 1 0xeeaaddbbaabbeedd [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}})
+; CHECK-SAME: [0x00000000
+; CHECK-NEXT: 2 0x00ffeeffaaff00ff [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}})
+; CHECK: [0x00000024
diff --git a/test/DebugInfo/dwarfdump-zlib.test b/test/DebugInfo/dwarfdump-zlib.test
index d3ef806f3f87..82f29afdebde 100644
--- a/test/DebugInfo/dwarfdump-zlib.test
+++ b/test/DebugInfo/dwarfdump-zlib.test
@@ -1,6 +1,7 @@
REQUIRES: zlib
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlib.elf-x86-64 | FileCheck %s
+RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlib.o.elf-x86-64 | FileCheck %s
RUN: llvm-dwarfdump %p/Inputs/dwarfdump-test-zlibgnu.elf-x86-64 | FileCheck %s
CHECK: .debug_abbrev contents
@@ -10,3 +11,7 @@ CHECK: .debug_abbrev contents
// that sections names are properly shown in zlib-gnu style (without additional 'z' prefix).
CHECK: .debug_info contents
CHECK: 0x00000000: Compile Unit: length = 0x00000144 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x08 (next unit at 0x00000148)
+
+// Also check that relocations in the .zdebug sections are handled correctly:
+CHECK: DW_AT_ranges {{.*}} (0x00000000{{$}}
+CHECK-NEXT: [0x
diff --git a/test/Instrumentation/InstrProfiling/always_inline.ll b/test/Instrumentation/InstrProfiling/always_inline.ll
new file mode 100644
index 000000000000..4be7848c9b6f
--- /dev/null
+++ b/test/Instrumentation/InstrProfiling/always_inline.ll
@@ -0,0 +1,28 @@
+; Check that '__attribute__((always_inline)) inline' functions are inlined.
+
+; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -instrprof -inline -S | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.13.0"
+
+@__profn_foo = linkonce_odr hidden constant [3 x i8] c"foo"
+
+; CHECK-LABEL: @main
+; CHECK-NOT: call
+define i32 @main() {
+entry:
+ %call = call i32 @foo()
+ ret i32 %call
+}
+
+declare void @llvm.instrprof.increment(i8*, i64, i32, i32) #0
+
+; CHECK-NOT: define available_externally i32 @foo
+define available_externally i32 @foo() #1 {
+entry:
+ call void @llvm.instrprof.increment(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @__profn_foo, i32 0, i32 0), i64 0, i32 1, i32 0)
+ ret i32 0
+}
+
+attributes #0 = { nounwind }
+attributes #1 = { alwaysinline }
diff --git a/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll b/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll
index 4df6ffeb5a8c..5b5b75117fb5 100644
--- a/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll
+++ b/test/Instrumentation/SanitizerCoverage/inline-8bit-counters.ll
@@ -10,4 +10,4 @@ entry:
; CHECK: store i8 %1, i8* getelementptr inbounds ([1 x i8], [1 x i8]* @__sancov_gen_, i64 0, i64 0), !nosanitize
ret void
}
-; CHECK: call void @__sanitizer_cov_8bit_counters_init(i8* bitcast (i8** @__start___sancov_counters to i8*), i8* bitcast (i8** @__stop___sancov_counters to i8*))
+; CHECK: call void @__sanitizer_cov_8bit_counters_init(i8* bitcast (i8** @__start___sancov_cntrs to i8*), i8* bitcast (i8** @__stop___sancov_cntrs to i8*))
diff --git a/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll b/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
new file mode 100644
index 000000000000..66754889f8ba
--- /dev/null
+++ b/test/LTO/Resolution/X86/Inputs/dead-strip-fulllto.ll
@@ -0,0 +1,16 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @live1() {
+ call void @live2()
+ ret void
+}
+
+declare void @live2()
+
+define void @dead1() {
+ call void @dead2()
+ ret void
+}
+
+declare void @dead2()
diff --git a/test/LTO/Resolution/X86/dead-strip-fulllto.ll b/test/LTO/Resolution/X86/dead-strip-fulllto.ll
new file mode 100644
index 000000000000..a9be2751c81f
--- /dev/null
+++ b/test/LTO/Resolution/X86/dead-strip-fulllto.ll
@@ -0,0 +1,37 @@
+; RUN: opt -module-summary -o %t %s
+; RUN: opt -module-summary -o %t2 %S/Inputs/dead-strip-fulllto.ll
+; RUN: llvm-lto2 run %t -r %t,main,px -r %t,live1,p -r %t,live2,p -r %t,dead2,p \
+; RUN: %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, \
+; RUN: -save-temps -o %t3
+; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s
+; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s
+
+; FULL-NOT: dead
+; FULL: U live1
+; FULL: T live2
+; FULL: T main
+
+; THIN-NOT: dead
+; THIN: T live1
+; THIN: U live2
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @main() {
+ call void @live1()
+ ret void
+}
+
+declare void @live1()
+
+define void @live2() {
+ ret void
+}
+
+define void @dead2() {
+ ret void
+}
+
+!0 = !{i32 1, !"ThinLTO", i32 0}
+!llvm.module.flags = !{ !0 }
diff --git a/test/LTO/Resolution/X86/symtab-elf.ll b/test/LTO/Resolution/X86/symtab-elf.ll
index 1683b061c6d6..d5f0fbe3700d 100644
--- a/test/LTO/Resolution/X86/symtab-elf.ll
+++ b/test/LTO/Resolution/X86/symtab-elf.ll
@@ -6,8 +6,8 @@ target triple = "x86_64-unknown-linux-gnu"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
; CHECK-NOT: linker opts:
-!0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}}
-!llvm.module.flags = !{ !0 }
+!0 = !{!"/include:foo"}
+!llvm.linker.options = !{ !0 }
@g1 = global i32 0
diff --git a/test/LTO/Resolution/X86/symtab.ll b/test/LTO/Resolution/X86/symtab.ll
index b7bc11749016..fecea0a1e7b4 100644
--- a/test/LTO/Resolution/X86/symtab.ll
+++ b/test/LTO/Resolution/X86/symtab.ll
@@ -9,8 +9,8 @@ target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
source_filename = "src.c"
; CHECK: linker opts: /include:foo
-!0 = !{i32 6, !"Linker Options", !{!{!"/include:foo"}}}
-!llvm.module.flags = !{ !0 }
+!0 = !{!"/include:foo"}
+!llvm.linker.options = !{ !0 }
; CHECK: D------X _fun
define i32 @fun() {
diff --git a/test/LibDriver/use-paths.test b/test/LibDriver/use-paths.test
new file mode 100644
index 000000000000..971c216127e6
--- /dev/null
+++ b/test/LibDriver/use-paths.test
@@ -0,0 +1,24 @@
+llvm-lib should behave like "link.exe /lib" and use relative paths to describe
+archive members.
+
+First, get in a clean working directory.
+RUN: rm -rf %t && mkdir -p %t && cd %t
+
+Make foo/a.obj and foo/b.obj.
+RUN: mkdir foo
+RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/a.obj %S/Inputs/a.s
+RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o foo/b.obj %S/Inputs/b.s
+
+RUN: llvm-lib -out:foo.lib foo/a.obj foo/b.obj
+RUN: llvm-ar t foo.lib | FileCheck %s
+
+FIXME: We should probably use backslashes on Windows to better match MSVC tools.
+CHECK: foo/a.obj
+CHECK: foo/b.obj
+
+Do it again with absolute paths and see that we get something.
+RUN: llvm-lib -out:foo.lib %t/foo/a.obj %t/foo/b.obj
+RUN: llvm-ar t foo.lib | FileCheck %s --check-prefix=ABS
+
+ABS: {{.*}}/foo/a.obj
+ABS: {{.*}}/foo/b.obj
diff --git a/test/MC/AMDGPU/flat-gfx9.s b/test/MC/AMDGPU/flat-gfx9.s
new file mode 100644
index 000000000000..5f93a7371b8b
--- /dev/null
+++ b/test/MC/AMDGPU/flat-gfx9.s
@@ -0,0 +1,40 @@
+// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx900 -show-encoding %s | FileCheck -check-prefix=GFX9 -check-prefix=GCN %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding %s | FileCheck -check-prefix=VI -check-prefix=GCN %s
+
+// RUN: not llvm-mc -arch=amdgcn -mcpu=gfx900 -show-encoding 2>&1 %s | FileCheck -check-prefix=GFX9-ERR -check-prefix=GCNERR %s
+// RUN: not llvm-mc -arch=amdgcn -mcpu=tonga -show-encoding 2>&1 %s | FileCheck -check-prefix=VI-ERR -check-prefix=GCNERR %s
+
+
+flat_load_dword v1, v[3:4] offset:0
+// GCN: flat_load_dword v1, v[3:4] ; encoding: [0x00,0x00,0x50,0xdc,0x03,0x00,0x00,0x01]
+
+flat_load_dword v1, v[3:4] offset:-1
+// GCN-ERR: :35: error: failed parsing operand.
+
+// FIXME: Error on VI in wrong column
+flat_load_dword v1, v[3:4] offset:4095
+// GFX9: flat_load_dword v1, v[3:4] offset:4095 ; encoding: [0xff,0x0f,0x50,0xdc,0x03,0x00,0x00,0x01]
+// VIERR: :1: error: invalid operand for instruction
+
+flat_load_dword v1, v[3:4] offset:4096
+// GCNERR: :28: error: invalid operand for instruction
+
+flat_load_dword v1, v[3:4] offset:4 glc
+// GFX9: flat_load_dword v1, v[3:4] offset:4 glc ; encoding: [0x04,0x00,0x51,0xdc,0x03,0x00,0x00,0x01]
+// VIERR: :1: error: invalid operand for instruction
+
+flat_load_dword v1, v[3:4] offset:4 glc slc
+// GFX9: flat_load_dword v1, v[3:4] offset:4 glc slc ; encoding: [0x04,0x00,0x53,0xdc,0x03,0x00,0x00,0x01]
+// VIERR: :1: error: invalid operand for instruction
+
+flat_atomic_add v[3:4], v5 offset:8 slc
+// GFX9: flat_atomic_add v[3:4], v5 offset:8 slc ; encoding: [0x08,0x00,0x0a,0xdd,0x03,0x05,0x00,0x00]
+// VIERR: :1: error: invalid operand for instruction
+
+flat_atomic_swap v[3:4], v5 offset:16
+// GFX9: flat_atomic_swap v[3:4], v5 offset:16 ; encoding: [0x10,0x00,0x00,0xdd,0x03,0x05,0x00,0x00]
+// VIERR: :1: error: invalid operand for instruction
+
+flat_store_dword v[3:4], v1 offset:16
+// GFX9: flat_store_dword v[3:4], v1 offset:16 ; encoding: [0x10,0x00,0x70,0xdc,0x03,0x01,0x00,0x00]
+// VIERR: :1: error: invalid operand for instruction
diff --git a/test/MC/AMDGPU/flat.s b/test/MC/AMDGPU/flat.s
index 4e81799fe9f9..d8cad131d1e4 100644
--- a/test/MC/AMDGPU/flat.s
+++ b/test/MC/AMDGPU/flat.s
@@ -49,9 +49,10 @@ flat_store_dword v[3:4], v1 slc
// FIXME: For atomic instructions, glc must be placed immediately following
// the data regiser. These forms aren't currently supported:
+// FIXME: offset:0 required
// flat_atomic_add v1, v[3:4], v5 slc glc
-flat_atomic_add v1 v[3:4], v5 glc slc
+flat_atomic_add v1, v[3:4], v5 offset:0 glc slc
// NOSI: error:
// CI: flat_atomic_add v1, v[3:4], v5 glc slc ; encoding: [0x00,0x00,0xcb,0xdc,0x03,0x05,0x00,0x01]
// VI: flat_atomic_add v1, v[3:4], v5 glc slc ; encoding: [0x00,0x00,0x0b,0xdd,0x03,0x05,0x00,0x01]
diff --git a/test/MC/COFF/cv-compiler-info.ll b/test/MC/COFF/cv-compiler-info.ll
index 6c33a25c1f46..f7cd17397d61 100644
--- a/test/MC/COFF/cv-compiler-info.ll
+++ b/test/MC/COFF/cv-compiler-info.ll
@@ -13,7 +13,7 @@ entry:
attributes #0 = { nounwind sspstrong "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
!llvm.dbg.cu = !{!0}
-!llvm.module.flags = !{!3, !7, !8}
+!llvm.module.flags = !{!7, !8}
!llvm.ident = !{!9}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
@@ -35,10 +35,6 @@ attributes #0 = { nounwind sspstrong "correctly-rounded-divide-sqrt-fp-math"="fa
; CHECK-NOT: .short 4412 # Record kind: S_COMPILE3
!1 = !DIFile(filename: "D:\5Csrc\5Cscopes\5Cfoo.cpp", directory: "D:\5Csrc\5Cscopes\5Cclang")
!2 = !{}
-!3 = !{i32 6, !"Linker Options", !4}
-!4 = !{!5, !6}
-!5 = !{!"/DEFAULTLIB:libcmtd.lib"}
-!6 = !{!"/DEFAULTLIB:oldnames.lib"}
!7 = !{i32 2, !"CodeView", i32 1}
!8 = !{i32 2, !"Debug Info Version", i32 3}
!9 = !{!"clang version 4.0.0 "}
diff --git a/test/MC/COFF/linker-options.ll b/test/MC/COFF/linker-options.ll
index afc55af692d2..24ac84da1e2d 100755
--- a/test/MC/COFF/linker-options.ll
+++ b/test/MC/COFF/linker-options.ll
@@ -1,8 +1,10 @@
; RUN: llc -O0 -mtriple=i386-pc-win32 -filetype=asm -o - %s | FileCheck %s
-!0 = !{i32 6, !"Linker Options", !{!{!"/DEFAULTLIB:msvcrt.lib"}, !{!"/DEFAULTLIB:msvcrt.lib", !"/DEFAULTLIB:secur32.lib"}, !{!"/DEFAULTLIB:\22C:\5Cpath to\5Casan_rt.lib\22"}, !{!"\22/with spaces\22"}}}
-
-!llvm.module.flags = !{ !0 }
+!0 = !{!"/DEFAULTLIB:msvcrt.lib"}
+!1 = !{!"/DEFAULTLIB:msvcrt.lib", !"/DEFAULTLIB:secur32.lib"}
+!2 = !{!"/DEFAULTLIB:\22C:\5Cpath to\5Casan_rt.lib\22"}
+!3 = !{!"\22/with spaces\22"}
+!llvm.linker.options = !{!0, !1, !2, !3}
define dllexport void @foo() {
ret void
diff --git a/test/MC/Disassembler/PowerPC/ppc64-encoding.txt b/test/MC/Disassembler/PowerPC/ppc64-encoding.txt
index a6d079297bcf..25ed35fcb1c0 100644
--- a/test/MC/Disassembler/PowerPC/ppc64-encoding.txt
+++ b/test/MC/Disassembler/PowerPC/ppc64-encoding.txt
@@ -352,6 +352,18 @@
# CHECK: divweu. 2, 3, 4
0x7c 0x43 0x23 0x17
+# CHECK: modsw 2, 3, 4
+0x7c 0x43 0x26 0x16
+
+# CHECK: moduw 2, 3, 4
+0x7c 0x43 0x22 0x16
+
+# CHECK: modsd 2, 3, 4
+0x7c 0x43 0x26 0x12
+
+# CHECK: modud 2, 3, 4
+0x7c 0x43 0x22 0x12
+
# CHECK: mulld 2, 3, 4
0x7c 0x43 0x21 0xd2
diff --git a/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt b/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt
index 9ddc286d8aaa..9dc994010551 100644
--- a/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt
+++ b/test/MC/Disassembler/PowerPC/ppc64le-encoding.txt
@@ -349,6 +349,18 @@
# CHECK: divweu. 2, 3, 4
0x17 0x23 0x43 0x7c
+# CHECK: modsw 2, 3, 4
+0x16 0x26 0x43 0x7c
+
+# CHECK: moduw 2, 3, 4
+0x16 0x22 0x43 0x7c
+
+# CHECK: modsd 2, 3, 4
+0x12 0x26 0x43 0x7c
+
+# CHECK: modud 2, 3, 4
+0x12 0x22 0x43 0x7c
+
# CHECK: mulld 2, 3, 4
0xd2 0x21 0x43 0x7c
diff --git a/test/MC/ELF/section.s b/test/MC/ELF/section.s
index 03a0f22e580b..c3f7d426ba56 100644
--- a/test/MC/ELF/section.s
+++ b/test/MC/ELF/section.s
@@ -267,3 +267,15 @@ bar:
// CHECK-NEXT: SHF_TLS
// CHECK-NEXT: SHF_WRITE
// CHECK-NEXT: ]
+
+// Test SHT_LLVM_ODRTAB
+
+.section .odrtab,"e",@llvm_odrtab
+// ASM: .section .odrtab,"e",@llvm_odrtab
+
+// CHECK: Section {
+// CHECK: Name: .odrtab
+// CHECK-NEXT: Type: SHT_LLVM_ODRTAB
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_EXCLUDE
+// CHECK-NEXT: ]
diff --git a/test/MC/MachO/linker-options.ll b/test/MC/MachO/linker-options.ll
index 09ebd0f91567..d9d7a4a46d8f 100644
--- a/test/MC/MachO/linker-options.ll
+++ b/test/MC/MachO/linker-options.ll
@@ -27,6 +27,7 @@
; CHECK-OBJ: ]
; CHECK-OBJ: }
-!0 = !{i32 6, !"Linker Options", !{!{!"-lz"}, !{!"-framework", !"Cocoa"}, !{!"-lmath"}}}
-
-!llvm.module.flags = !{ !0 }
+!0 = !{!"-lz"}
+!1 = !{!"-framework", !"Cocoa"}
+!2 = !{!"-lmath"}
+!llvm.linker.options = !{!0, !1, !2}
diff --git a/test/MC/PowerPC/ppc64-encoding.s b/test/MC/PowerPC/ppc64-encoding.s
index a772ca44986c..237dd5cfd727 100644
--- a/test/MC/PowerPC/ppc64-encoding.s
+++ b/test/MC/PowerPC/ppc64-encoding.s
@@ -493,6 +493,19 @@
# FIXME: divweuo 2, 3, 4
# FIXME: divweuo. 2, 3, 4
+# CHECK-BE: modsw 2, 3, 4 # encoding: [0x7c,0x43,0x26,0x16]
+# CHECK-LE: modsw 2, 3, 4 # encoding: [0x16,0x26,0x43,0x7c]
+ modsw 2, 3, 4
+# CHECK-BE: moduw 2, 3, 4 # encoding: [0x7c,0x43,0x22,0x16]
+# CHECK-LE: moduw 2, 3, 4 # encoding: [0x16,0x22,0x43,0x7c]
+ moduw 2, 3, 4
+# CHECK-BE: modsd 2, 3, 4 # encoding: [0x7c,0x43,0x26,0x12]
+# CHECK-LE: modsd 2, 3, 4 # encoding: [0x12,0x26,0x43,0x7c]
+ modsd 2, 3, 4
+# CHECK-BE: modud 2, 3, 4 # encoding: [0x7c,0x43,0x22,0x12]
+# CHECK-LE: modud 2, 3, 4 # encoding: [0x12,0x22,0x43,0x7c]
+ modud 2, 3, 4
+
# CHECK-BE: mulld 2, 3, 4 # encoding: [0x7c,0x43,0x21,0xd2]
# CHECK-LE: mulld 2, 3, 4 # encoding: [0xd2,0x21,0x43,0x7c]
mulld 2, 3, 4
diff --git a/test/MC/WebAssembly/external-data.ll b/test/MC/WebAssembly/external-data.ll
index 91e05b3f13a6..6914736ac671 100644
--- a/test/MC/WebAssembly/external-data.ll
+++ b/test/MC/WebAssembly/external-data.ll
@@ -2,10 +2,10 @@
; Verify relocations are correctly generated for addresses of externals
; in the data section.
-declare i32 @f1(...)
+@myimport = external global i32, align 4
@foo = global i64 7, align 4
-@far = local_unnamed_addr global i32 (...)* @f1, align 4
+@bar = hidden global i32* @myimport, align 4
; CHECK: - Type: DATA
; CHECK: Relocations:
diff --git a/test/MC/WebAssembly/external-func-address.ll b/test/MC/WebAssembly/external-func-address.ll
new file mode 100644
index 000000000000..4022b2c9bae9
--- /dev/null
+++ b/test/MC/WebAssembly/external-func-address.ll
@@ -0,0 +1,25 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s
+; Verify that addresses of external functions generate correctly typed
+; imports and relocations or type R_TABLE_INDEX_I32.
+
+declare void @f1() #1
+@ptr_to_f1 = hidden global void ()* @f1, align 4
+
+
+; CHECK: - Type: IMPORT
+; CHECK: Imports:
+; CHECK: - Module: env
+; CHECK: Field: f1
+; CHECK: Kind: FUNCTION
+; CHECK: SigIndex: 0
+; CHECK: - Type: ELEM
+; CHECK: Segments:
+; CHECK: - Offset:
+; CHECK: Opcode: I32_CONST
+; CHECK: Value: 0
+; CHECK: Functions: [ 0 ]
+; CHECK: - Type: DATA
+; CHECK: Relocations:
+; CHECK: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
+; CHECK: Index: 0
+; CHECK: Offset: 0x00000006
diff --git a/test/MC/WebAssembly/func-address.ll b/test/MC/WebAssembly/func-address.ll
new file mode 100644
index 000000000000..c0a9d9a801ff
--- /dev/null
+++ b/test/MC/WebAssembly/func-address.ll
@@ -0,0 +1,48 @@
+; RUN: llc -mtriple wasm32-unknown-unknown-wasm -O2 -filetype=obj %s -o - | llvm-readobj -r -s -expand-relocs | FileCheck %s
+
+declare i32 @import1()
+declare i32 @import2()
+declare i32 @import3()
+
+; call the imports to make sure they are included in the imports section
+define hidden void @call_imports() #0 {
+entry:
+ %call = call i32 @import1()
+ %call1 = call i32 @import2()
+ ret void
+}
+
+; take the address of the third import. This should generate a TABLE_INDEX
+; relocation with index of 0 since its the first and only address taken
+; function.
+define hidden void @call_indirect() #0 {
+entry:
+ %adr = alloca i32 ()*, align 4
+ store i32 ()* @import3, i32 ()** %adr, align 4
+ ret void
+}
+
+; CHECK: Section {
+; CHECK: Type: ELEM (0x9)
+; CHECK: Size: 7
+; CHECK: Offset: 165
+; CHECK: }
+
+; CHECK: Relocations [
+; CHECK: Section (9) CODE {
+; CHECK: Relocation {
+; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0)
+; CHECK: Offset: 0x4
+; CHECK: Index: 0x0
+; CHECK: }
+; CHECK: Relocation {
+; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0)
+; CHECK: Offset: 0xB
+; CHECK: Index: 0x1
+; CHECK: }
+; CHECK: Relocation {
+; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1)
+; CHECK: Offset: 0x1A
+; CHECK: Index: 0x0
+; CHECK: }
+; CHECK: }
diff --git a/test/ThinLTO/X86/cfi-icall.ll b/test/ThinLTO/X86/cfi-icall.ll
new file mode 100644
index 000000000000..ef5d33c8a5a0
--- /dev/null
+++ b/test/ThinLTO/X86/cfi-icall.ll
@@ -0,0 +1,29 @@
+; RUN: opt -thinlto-bc %s -o %t1.bc
+; RUN: llvm-lto2 run -thinlto-distributed-indexes %t1.bc -o %t.out -save-temps \
+; RUN: -r %t1.bc,foo,plx \
+; RUN: -r %t1.bc,bar,x
+; RUN: llvm-bcanalyzer -dump %t.out.index.bc | FileCheck %s --check-prefix=COMBINED
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i1 @foo(i8* %p) !type !0 {
+entry:
+ %x = call i1 @llvm.type.test(i8* %p, metadata !"typeid1")
+ ret i1 %x
+}
+
+declare !type !0 void @bar()
+
+declare i1 @llvm.type.test(i8* %ptr, metadata %type) nounwind readnone
+
+!0 = !{i64 0, !"typeid1"}
+
+; COMBINED: <GLOBALVAL_SUMMARY_BLOCK
+; COMBINED: <CFI_FUNCTION_DEFS op0=0 op1=3/>
+; COMBINED: <CFI_FUNCTION_DECLS op0=3 op1=3/>
+; COMBINED: </GLOBALVAL_SUMMARY_BLOCK>
+
+; COMBINED: <STRTAB_BLOCK
+; COMBINED-NEXT: <BLOB abbrevid=4/> blob data = 'foobar'
+; COMBINED-NEXT: </STRTAB_BLOCK>
diff --git a/test/Transforms/CodeExtractor/live_shrink.ll b/test/Transforms/CodeExtractor/live_shrink.ll
new file mode 100644
index 000000000000..c25ed2b622cd
--- /dev/null
+++ b/test/Transforms/CodeExtractor/live_shrink.ll
@@ -0,0 +1,67 @@
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+ %tmp2 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp3 = icmp eq i32 %tmp2, 0
+ br i1 %tmp3, label %bb4, label %bb5
+
+bb4: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+; CHECK-LABEL: @_Z3goov()
+bb:
+; CHECK: bb:
+; CHECK-NOT: alloca
+; CHECK-NOT: bitcast
+; CHECK-NOT: llvm.lifetime
+; CHECK: br i1
+; CHECK: codeRepl.i:
+; CHECK: call void @_Z3foov.1_
+
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1_
+; CHECK: newFuncRoot:
+; CHECK-NEXT: %tmp = alloca %class.A
+; CHECK-NEXT: %tmp1 = bitcast %class.A* %tmp to i8*
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+; CHECK-NEXT: br label %bb5.exitStub
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
diff --git a/test/Transforms/CodeExtractor/live_shrink_gep.ll b/test/Transforms/CodeExtractor/live_shrink_gep.ll
new file mode 100644
index 000000000000..ac6aa4fbda43
--- /dev/null
+++ b/test/Transforms/CodeExtractor/live_shrink_gep.ll
@@ -0,0 +1,66 @@
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i8 }
+
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 1
+ %tmp1 = getelementptr inbounds %class.A, %class.A* %tmp, i64 0, i32 0
+ call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %tmp1)
+ %tmp2 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp3 = icmp eq i32 %tmp2, 0
+ br i1 %tmp3, label %bb4, label %bb5
+
+bb4: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb5
+
+bb5: ; preds = %bb4, %bb
+ call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull %tmp1)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+; CHECK-LABEL: @_Z3goov()
+bb:
+; CHECK: bb:
+; CHECK-NOT: alloca
+; CHECK-NOT: getelementptr
+; CHECK-NOT: llvm.lifetime
+; CHECK: br i1
+; CHECK: codeRepl.i:
+; CHECK: call void @_Z3foov.1_
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1_
+; CHECK: newFuncRoot:
+; CHECK-NEXT: %tmp = alloca %class.A
+; CHECK-NEXT: %tmp1 = getelementptr
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
+; CHECK: call void @llvm.lifetime.end.p0i8
+; CHECK-NEXT: br label %bb5.exitStub
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
diff --git a/test/Transforms/CodeExtractor/live_shrink_hoist.ll b/test/Transforms/CodeExtractor/live_shrink_hoist.ll
new file mode 100644
index 000000000000..d1b310f01769
--- /dev/null
+++ b/test/Transforms/CodeExtractor/live_shrink_hoist.ll
@@ -0,0 +1,66 @@
+; RUN: opt -S -partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -max-num-inline-blocks=2 -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+ %tmp2 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp3 = icmp eq i32 %tmp2, 0
+ br i1 %tmp3, label %bb4, label %bb9
+
+bb4: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ %tmp5 = getelementptr inbounds %class.A, %class.A* %tmp, i64 0, i32 0
+ %tmp6 = load i32, i32* %tmp5, align 4, !tbaa !6
+ %tmp7 = icmp sgt i32 %tmp6, 0
+ br i1 %tmp7, label %bb9, label %bb8
+
+bb8: ; preds = %bb4
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb9
+
+bb9: ; preds = %bb8, %bb4, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+bb:
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1_
+; CHECK: bb9:
+; CHECK: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+; CHECK: br label %.exitStub
+
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
+!6 = !{!7, !3, i64 0}
+!7 = !{!"_ZTS1A", !3, i64 0}
diff --git a/test/Transforms/CodeExtractor/live_shrink_multiple.ll b/test/Transforms/CodeExtractor/live_shrink_multiple.ll
new file mode 100644
index 000000000000..8d9045c7267b
--- /dev/null
+++ b/test/Transforms/CodeExtractor/live_shrink_multiple.ll
@@ -0,0 +1,66 @@
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+@cond = local_unnamed_addr global i32 0, align 4
+
+; Function Attrs: uwtable
+define void @_Z3foov() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = alloca %class.A, align 4
+ %tmp2 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp2)
+ %tmp3 = bitcast %class.A* %tmp1 to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp3)
+ %tmp4 = load i32, i32* @cond, align 4, !tbaa !2
+ %tmp5 = icmp eq i32 %tmp4, 0
+ br i1 %tmp5, label %bb6, label %bb7
+
+bb6: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb7
+
+bb7: ; preds = %bb6, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp3)
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp2)
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+; Function Attrs: uwtable
+define void @_Z3goov() local_unnamed_addr {
+bb:
+ tail call void @_Z3foov()
+ ret void
+}
+
+; CHECK-LABEL: define internal void @_Z3foov.1_
+; CHECK: newFuncRoot:
+; CHECK-NEXT: alloca
+; CHECK-NEXT: bitcast
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
+; CHECK-NEXT: alloca
+; CHECK-NEXT: bitcast
+; CHECK-NEXT: call void @llvm.lifetime.start.p0i8
+; CHECK: call void @llvm.lifetime.end.p0i8
+; CHECK-NEXT: call void @llvm.lifetime.end.p0i8
+; CHECK-NEXT: br label {{.*}}exitStub
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"int", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
diff --git a/test/Transforms/CodeExtractor/live_shrink_unsafe.ll b/test/Transforms/CodeExtractor/live_shrink_unsafe.ll
new file mode 100644
index 000000000000..ea6458cc46ec
--- /dev/null
+++ b/test/Transforms/CodeExtractor/live_shrink_unsafe.ll
@@ -0,0 +1,94 @@
+; The expected behavior of this file is expected to change when partial
+; inlining legality check is enhanced.
+
+; RUN: opt -S -partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+; RUN: opt -S -passes=partial-inliner -skip-partial-inlining-cost-analysis < %s | FileCheck %s
+
+%class.A = type { i32 }
+
+@cond = local_unnamed_addr global i32 0, align 4
+@condptr = external local_unnamed_addr global i32*, align 8
+
+; Function Attrs: uwtable
+define void @_Z3foo_unknown_mem_accessv() local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = alloca %class.A, align 4
+ %tmp2 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp2)
+ %tmp3 = bitcast %class.A* %tmp1 to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp3)
+ %tmp4 = load i32*, i32** @condptr, align 8, !tbaa !2
+ %tmp5 = load i32, i32* %tmp4, align 4, !tbaa !6
+ %tmp6 = icmp eq i32 %tmp5, 0
+ br i1 %tmp6, label %bb7, label %bb8
+
+bb7: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb8
+
+bb8: ; preds = %bb7, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp3)
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp2)
+ ret void
+}
+
+declare void @_Z3barv() local_unnamed_addr
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare void @_ZN1A7memfuncEv(%class.A*) local_unnamed_addr
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
+define void @_Z3foo_unknown_calli(i32 %arg) local_unnamed_addr {
+bb:
+ %tmp = alloca %class.A, align 4
+ %tmp1 = bitcast %class.A* %tmp to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %tmp1)
+ tail call void @_Z3barv()
+ %tmp2 = icmp eq i32 %arg, 0
+ br i1 %tmp2, label %bb3, label %bb4
+
+bb3: ; preds = %bb
+ call void @_ZN1A7memfuncEv(%class.A* nonnull %tmp)
+ br label %bb4
+
+bb4: ; preds = %bb3, %bb
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %tmp1)
+ ret void
+}
+
+define void @_Z3goov() local_unnamed_addr {
+; CHECK-LABEL: @_Z3goov
+; CHECK-NEXT: bb:
+; CHECK: alloca
+; CHECK: lifetime
+bb:
+ call void @_Z3foo_unknown_mem_accessv()
+ %tmp = load i32, i32* @cond, align 4, !tbaa !2
+ tail call void @_Z3foo_unknown_calli(i32 %tmp)
+ ret void
+}
+
+; CHECK-LABEL define internal void @_Z3foo_unknown_calli.1_bb3
+; CHECK: newFuncRoot:
+; CHECK-NEXT: br label %bb3
+
+; CHECK: bb4.exitStub:
+; CHECK-NEXT: ret void
+
+; CHECK: bb3:
+; CHECK-NOT: lifetime.ed
+; CHECK: br label %bb4.exitStub
+
+
+
+!llvm.module.flags = !{!0}
+!llvm.ident = !{!1}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{!"clang version 5.0.0 (trunk 304489)"}
+!2 = !{!3, !3, i64 0}
+!3 = !{!"any pointer", !4, i64 0}
+!4 = !{!"omnipotent char", !5, i64 0}
+!5 = !{!"Simple C++ TBAA"}
+!6 = !{!7, !7, i64 0}
+!7 = !{!"int", !4, i64 0}
diff --git a/test/Transforms/CrossDSOCFI/cfi_functions.ll b/test/Transforms/CrossDSOCFI/cfi_functions.ll
new file mode 100644
index 000000000000..ccbde51b2115
--- /dev/null
+++ b/test/Transforms/CrossDSOCFI/cfi_functions.ll
@@ -0,0 +1,23 @@
+; Test that types referenced in ThinLTO-style !cfi.functions are known to __cfi_check.
+; RUN: opt -S -cross-dso-cfi < %s | FileCheck %s
+; RUN: opt -S -passes=cross-dso-cfi < %s | FileCheck %s
+
+; CHECK: define void @__cfi_check(
+; CHECK: switch i64
+; CHECK-NEXT: i64 1234, label
+; CHECK-NEXT: i64 5678, label
+; CHECK-NEXT: ]
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+!cfi.functions = !{!0, !1}
+!llvm.module.flags = !{!6}
+
+!0 = !{!"f", i8 0, !2, !4}
+!1 = !{!"g", i8 1, !3, !5}
+!2 = !{i64 0, !"typeid1"}
+!3 = !{i64 0, !"typeid2"}
+!4 = !{i64 0, i64 1234}
+!5 = !{i64 0, i64 5678}
+!6 = !{i32 4, !"Cross-DSO CFI", i32 1}
diff --git a/test/Transforms/EarlyCSE/pr33406.ll b/test/Transforms/EarlyCSE/pr33406.ll
new file mode 100644
index 000000000000..4d3312e1f0ac
--- /dev/null
+++ b/test/Transforms/EarlyCSE/pr33406.ll
@@ -0,0 +1,26 @@
+; RUN: opt -early-cse-memssa -S %s | FileCheck %s
+
+; CHECK: define void @patatino() {
+; CHECK: for.cond:
+; CHECK-NEXT: br i1 true, label %if.end, label %for.inc
+; CHECK: if.end:
+; CHECK-NEXT: %tinkywinky = load i32, i32* @b
+; CHECK-NEXT: br i1 true, label %for.inc, label %for.inc
+; CHECK: for.inc:
+; CHECK-NEXT: ret void
+
+
+@b = external global i32
+
+define void @patatino() {
+for.cond:
+ br i1 true, label %if.end, label %for.inc
+
+if.end:
+ %tinkywinky = load i32, i32* @b
+ store i32 %tinkywinky, i32* @b
+ br i1 true, label %for.inc, label %for.inc
+
+for.inc:
+ ret void
+}
diff --git a/test/Transforms/GVN/pr32314.ll b/test/Transforms/GVN/pr32314.ll
new file mode 100644
index 000000000000..90d14f6fc49c
--- /dev/null
+++ b/test/Transforms/GVN/pr32314.ll
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S -gvn < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; The load in the loop can not bypass the data from the previous loop. The store above it in the loop aliases.
+define void @foo() {
+; CHECK-LABEL: @foo(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[A:%.*]] = alloca [3 x i32], align 4
+; CHECK-NEXT: br label [[FOR_BODY:%.*]]
+; CHECK: for.cond.cleanup:
+; CHECK-NEXT: ret void
+; CHECK: for.body:
+; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[P_017:%.*]] = phi i32* [ undef, [[ENTRY]] ], [ [[ARRAYIDX3:%.*]], [[FOR_BODY]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[INDVARS_IV]], -1
+; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [3 x i32], [3 x i32]* [[A]], i64 0, i64 [[TMP0]]
+; CHECK-NEXT: store i32 50, i32* [[ARRAYIDX]], align 4
+; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[P_017]], align 4
+; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP1]] to i32
+; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[TMP2]], [[TMP3]]
+; CHECK-NEXT: [[ARRAYIDX3]] = getelementptr inbounds [3 x i32], [3 x i32]* [[A]], i64 0, i64 [[INDVARS_IV]]
+; CHECK-NEXT: store i32 60, i32* [[ARRAYIDX3]], align 4
+; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
+; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 3
+; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]]
+;
+entry:
+ %a = alloca [3 x i32], align 4
+ br label %for.body
+
+for.cond.cleanup: ; preds = %for.body
+ ret void
+
+for.body: ; preds = %for.body, %entry
+ %indvars.iv = phi i64 [ 1, %entry ], [ %indvars.iv.next, %for.body ]
+ %p.017 = phi i32* [ undef, %entry ], [ %arrayidx3, %for.body ]
+ %0 = add nsw i64 %indvars.iv, -1
+ %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* %a, i64 0, i64 %0
+ store i32 50, i32* %arrayidx, align 4
+ %1 = shl i64 %indvars.iv, 1
+ %2 = load i32, i32* %p.017, align 4
+ %3 = trunc i64 %1 to i32
+ %add1 = add nsw i32 %2, %3
+ %arrayidx3 = getelementptr inbounds [3 x i32], [3 x i32]* %a, i64 0, i64 %indvars.iv
+ store i32 60, i32* %arrayidx3, align 4
+ %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+ %exitcond = icmp ne i64 %indvars.iv.next, 3
+ br i1 %exitcond, label %for.body, label %for.cond.cleanup
+}
diff --git a/test/Transforms/GlobalMerge/debug-info.ll b/test/Transforms/GlobalMerge/debug-info.ll
index 97e0bb2148e9..8d60f3662431 100644
--- a/test/Transforms/GlobalMerge/debug-info.ll
+++ b/test/Transforms/GlobalMerge/debug-info.ll
@@ -17,7 +17,7 @@ define void @use1() {
; CHECK: [[AVAR]] = !DIGlobalVariable(name: "a", scope: null, isLocal: false, isDefinition: true)
; CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BVAR:![0-9]+]], expr: [[EXPR:![0-9]+]])
; CHECK: [[BVAR]] = !DIGlobalVariable(name: "b", scope: null, isLocal: false, isDefinition: true)
-; CHECK: [[EXPR]] = !DIExpression(DW_OP_plus, 4)
+; CHECK: [[EXPR]] = !DIExpression(DW_OP_plus_uconst, 4)
!llvm.module.flags = !{!4, !5}
diff --git a/test/Transforms/Inline/always-inline.ll b/test/Transforms/Inline/always-inline.ll
index 5366b5a16cc7..791eb94779b7 100644
--- a/test/Transforms/Inline/always-inline.ll
+++ b/test/Transforms/Inline/always-inline.ll
@@ -305,3 +305,14 @@ entry:
ret void
; CHECK: ret void
}
+
+define void @inner14() readnone nounwind {
+; CHECK: define void @inner14
+ ret void
+}
+
+define void @outer14() {
+; CHECK: call void @inner14
+ call void @inner14()
+ ret void
+}
diff --git a/test/Transforms/InstCombine/debuginfo-dce.ll b/test/Transforms/InstCombine/debuginfo-dce.ll
index 086743e80820..50b8f1c6068e 100644
--- a/test/Transforms/InstCombine/debuginfo-dce.ll
+++ b/test/Transforms/InstCombine/debuginfo-dce.ll
@@ -93,12 +93,12 @@ entry:
ret void, !dbg !32
}
-; CHECK: ![[LOAD_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_plus, 0)
-; CHECK: ![[BITCAST_EXPR]] = !DIExpression(DW_OP_plus, 0)
-; CHECK: ![[GEP0_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_plus, 0, DW_OP_stack_value)
-; CHECK: ![[GEP1_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value,
+; CHECK: ![[LOAD_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 0)
+; CHECK: ![[BITCAST_EXPR]] = !DIExpression(DW_OP_plus_uconst, 0)
+; CHECK: ![[GEP0_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_plus_uconst, 0, DW_OP_stack_value)
+; CHECK: ![[GEP1_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_stack_value,
; CHECK-SAME: DW_OP_LLVM_fragment, 0, 32)
-; CHECK: ![[GEP2_EXPR]] = !DIExpression(DW_OP_minus, 8, DW_OP_stack_value)
+; CHECK: ![[GEP2_EXPR]] = !DIExpression(DW_OP_constu, 8, DW_OP_minus, DW_OP_stack_value)
; Function Attrs: nounwind readnone
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1
@@ -130,7 +130,7 @@ attributes #1 = { nounwind readnone }
!17 = !{!18}
!18 = !DILocalVariable(name: "entry", scope: !14, file: !1, line: 6, type: !4)
!19 = !DILocation(line: 6, column: 17, scope: !14)
-!20 = !DIExpression(DW_OP_plus, 0)
+!20 = !DIExpression(DW_OP_plus_uconst, 0)
!21 = !DILocation(line: 11, column: 1, scope: !14)
!22 = distinct !DISubprogram(name: "scan", scope: !1, file: !1, line: 4, type: !15, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !17)
!23 = !DILocation(line: 6, column: 17, scope: !22)
diff --git a/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll b/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll
index 107440f10a5a..230ac1796671 100644
--- a/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll
+++ b/test/Transforms/InstCombine/element-atomic-memcpy-to-loads.ll
@@ -1,10 +1,11 @@
; RUN: opt -instcombine -unfold-element-atomic-memcpy-max-elements=8 -S < %s | FileCheck %s
+; Temporarily an expected failure until inst combine is updated in the next patch
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-; Test basic unfolding
-define void @test1(i8* %Src, i8* %Dst) {
-; CHECK-LABEL: test1
-; CHECK-NOT: llvm.memcpy.element.atomic
+; Test basic unfolding -- unordered load & store
+define void @test1a(i8* %Src, i8* %Dst) {
+; CHECK-LABEL: test1a
+; CHECK-NOT: llvm.memcpy.element.unordered.atomic
; CHECK-DAG: %memcpy_unfold.src_casted = bitcast i8* %Src to i32*
; CHECK-DAG: %memcpy_unfold.dst_casted = bitcast i8* %Dst to i32*
@@ -21,7 +22,7 @@ define void @test1(i8* %Src, i8* %Dst) {
; CHECK-DAG: [[VAL4:%[^\s]+]] = load atomic i32, i32* %{{[^\s]+}} unordered, align 4
; CHECK-DAG: store atomic i32 [[VAL4]], i32* %{{[^\s]+}} unordered, align 4
entry:
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dst, i8* align 8 %Src, i64 4, i32 4)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 8 %Dst, i8* align 4 %Src, i32 16, i32 4)
ret void
}
@@ -31,9 +32,9 @@ define void @test2(i8* %Src, i8* %Dst) {
; CHECK-NOT: load
; CHECK-NOT: store
-; CHECK: llvm.memcpy.element.atomic
+; CHECK: llvm.memcpy.element.unordered.atomic
entry:
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dst, i8* align 4 %Src, i64 1000, i32 4)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 8 %Dst, i8* align 4 %Src, i32 256, i32 4)
ret void
}
@@ -43,16 +44,16 @@ define void @test3(i8* %Src, i8* %Dst) {
; CHECK-NOT: load
; CHECK-NOT: store
-; CHECK: llvm.memcpy.element.atomic
+; CHECK: llvm.memcpy.element.unordered.atomic
entry:
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 64 %Dst, i8* align 64 %Src, i64 4, i32 64)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 64 %Dst, i8* align 64 %Src, i32 64, i32 64)
ret void
}
; Test that we will eliminate redundant bitcasts
define void @test4(i64* %Src, i64* %Dst) {
; CHECK-LABEL: test4
-; CHECK-NOT: llvm.memcpy.element.atomic
+; CHECK-NOT: llvm.memcpy.element.unordered.atomic
; CHECK-NOT: bitcast
@@ -76,17 +77,18 @@ define void @test4(i64* %Src, i64* %Dst) {
entry:
%Src.casted = bitcast i64* %Src to i8*
%Dst.casted = bitcast i64* %Dst to i8*
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 16 %Dst.casted, i8* align 16 %Src.casted, i64 4, i32 8)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 16 %Dst.casted, i8* align 16 %Src.casted, i32 32, i32 8)
ret void
}
+; Test that 0-length unordered atomic memcpy gets removed.
define void @test5(i8* %Src, i8* %Dst) {
; CHECK-LABEL: test5
-; CHECK-NOT: llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 64 %Dst, i8* align 64 %Src, i64 0, i32 64)
+; CHECK-NOT: llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 64 %Dst, i8* align 64 %Src, i32 0, i32 8)
entry:
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 64 %Dst, i8* align 64 %Src, i64 0, i32 64)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 64 %Dst, i8* align 64 %Src, i32 0, i32 8)
ret void
}
-declare void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* nocapture, i8* nocapture, i64, i32)
+declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind
diff --git a/test/Transforms/InstCombine/ffs-1.ll b/test/Transforms/InstCombine/ffs-1.ll
index d27fb5d89f09..af4ee85216ef 100644
--- a/test/Transforms/InstCombine/ffs-1.ll
+++ b/test/Transforms/InstCombine/ffs-1.ll
@@ -1,12 +1,12 @@
; Test that the ffs* library call simplifier works correctly.
;
-; RUN: opt < %s -instcombine -S | FileCheck %s
-; RUN: opt < %s -mtriple i386-pc-linux -instcombine -S | FileCheck %s -check-prefix=CHECK-FFS
-; RUN: opt -instcombine -mtriple=arm64-apple-ios9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s
-; RUN: opt -instcombine -mtriple=arm64-apple-tvos9.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s
-; RUN: opt -instcombine -mtriple=thumbv7k-apple-watchos2.0 -S %s | FileCheck --check-prefix=CHECK-FFS %s
-; RUN: opt -instcombine -mtriple=x86_64-apple-macosx10.11 -S %s | FileCheck --check-prefix=CHECK-FFS %s
-; RUN: opt -instcombine -mtriple=x86_64-freebsd-gnu -S %s | FileCheck --check-prefix=CHECK-FFS %s
+; RUN: opt < %s -instcombine -S | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC
+; RUN: opt < %s -instcombine -mtriple i386-pc-linux -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET
+; RUN: opt < %s -instcombine -mtriple=arm64-apple-ios9.0 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET
+; RUN: opt < %s -instcombine -mtriple=arm64-apple-tvos9.0 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET
+; RUN: opt < %s -instcombine -mtriple=thumbv7k-apple-watchos2.0 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET
+; RUN: opt < %s -instcombine -mtriple=x86_64-apple-macosx10.11 -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET
+; RUN: opt < %s -instcombine -mtriple=x86_64-freebsd-gnu -S | FileCheck %s --check-prefix=ALL --check-prefix=TARGET
declare i32 @ffs(i32)
declare i32 @ffsl(i32)
@@ -15,123 +15,179 @@ declare i32 @ffsll(i64)
; Check ffs(0) -> 0.
define i32 @test_simplify1() {
-; CHECK-LABEL: @test_simplify1(
+; ALL-LABEL: @test_simplify1(
+; ALL-NEXT: ret i32 0
+;
%ret = call i32 @ffs(i32 0)
ret i32 %ret
-; CHECK-NEXT: ret i32 0
}
define i32 @test_simplify2() {
-; CHECK-FFS-LABEL: @test_simplify2(
+; GENERIC-LABEL: @test_simplify2(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsl(i32 0)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify2(
+; TARGET-NEXT: ret i32 0
+;
%ret = call i32 @ffsl(i32 0)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 0
}
define i32 @test_simplify3() {
-; CHECK-FFS-LABEL: @test_simplify3(
+; GENERIC-LABEL: @test_simplify3(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 0)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify3(
+; TARGET-NEXT: ret i32 0
+;
%ret = call i32 @ffsll(i64 0)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 0
}
; Check ffs(c) -> cttz(c) + 1, where 'c' is a constant.
define i32 @test_simplify4() {
-; CHECK-LABEL: @test_simplify4(
+; ALL-LABEL: @test_simplify4(
+; ALL-NEXT: ret i32 1
+;
%ret = call i32 @ffs(i32 1)
ret i32 %ret
-; CHECK-NEXT: ret i32 1
}
define i32 @test_simplify5() {
-; CHECK-LABEL: @test_simplify5(
+; ALL-LABEL: @test_simplify5(
+; ALL-NEXT: ret i32 12
+;
%ret = call i32 @ffs(i32 2048)
ret i32 %ret
-; CHECK-NEXT: ret i32 12
}
define i32 @test_simplify6() {
-; CHECK-LABEL: @test_simplify6(
+; ALL-LABEL: @test_simplify6(
+; ALL-NEXT: ret i32 17
+;
%ret = call i32 @ffs(i32 65536)
ret i32 %ret
-; CHECK-NEXT: ret i32 17
}
define i32 @test_simplify7() {
-; CHECK-FFS-LABEL: @test_simplify7(
+; GENERIC-LABEL: @test_simplify7(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsl(i32 65536)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify7(
+; TARGET-NEXT: ret i32 17
+;
%ret = call i32 @ffsl(i32 65536)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 17
}
define i32 @test_simplify8() {
-; CHECK-FFS-LABEL: @test_simplify8(
+; GENERIC-LABEL: @test_simplify8(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 1024)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify8(
+; TARGET-NEXT: ret i32 11
+;
%ret = call i32 @ffsll(i64 1024)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 11
}
define i32 @test_simplify9() {
-; CHECK-FFS-LABEL: @test_simplify9(
+; GENERIC-LABEL: @test_simplify9(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 65536)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify9(
+; TARGET-NEXT: ret i32 17
+;
%ret = call i32 @ffsll(i64 65536)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 17
}
define i32 @test_simplify10() {
-; CHECK-FFS-LABEL: @test_simplify10(
+; GENERIC-LABEL: @test_simplify10(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 17179869184)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify10(
+; TARGET-NEXT: ret i32 35
+;
%ret = call i32 @ffsll(i64 17179869184)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 35
}
define i32 @test_simplify11() {
-; CHECK-FFS-LABEL: @test_simplify11(
+; GENERIC-LABEL: @test_simplify11(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 281474976710656)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify11(
+; TARGET-NEXT: ret i32 49
+;
%ret = call i32 @ffsll(i64 281474976710656)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 49
}
define i32 @test_simplify12() {
-; CHECK-FFS-LABEL: @test_simplify12(
+; GENERIC-LABEL: @test_simplify12(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 1152921504606846976)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify12(
+; TARGET-NEXT: ret i32 61
+;
%ret = call i32 @ffsll(i64 1152921504606846976)
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 61
}
; Check ffs(x) -> x != 0 ? (i32)llvm.cttz(x) + 1 : 0.
define i32 @test_simplify13(i32 %x) {
-; CHECK-LABEL: @test_simplify13(
+; ALL-LABEL: @test_simplify13(
+; ALL-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+; ALL-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[CTTZ]], 1
+; ALL-NEXT: [[TMP2:%.*]] = icmp ne i32 %x, 0
+; ALL-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 0
+; ALL-NEXT: ret i32 [[TMP3]]
+;
%ret = call i32 @ffs(i32 %x)
-; CHECK-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true)
-; CHECK-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1
-; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0
-; CHECK-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0
ret i32 %ret
-; CHECK-NEXT: ret i32 [[RET]]
}
define i32 @test_simplify14(i32 %x) {
-; CHECK-FFS-LABEL: @test_simplify14(
+; GENERIC-LABEL: @test_simplify14(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsl(i32 %x)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify14(
+; TARGET-NEXT: [[CTTZ:%.*]] = call i32 @llvm.cttz.i32(i32 %x, i1 true)
+; TARGET-NEXT: [[TMP1:%.*]] = add nuw nsw i32 [[CTTZ]], 1
+; TARGET-NEXT: [[TMP2:%.*]] = icmp ne i32 %x, 0
+; TARGET-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[TMP1]], i32 0
+; TARGET-NEXT: ret i32 [[TMP3]]
+;
%ret = call i32 @ffsl(i32 %x)
-; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %x, i1 true)
-; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i32 [[CTTZ]], 1
-; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i32 %x, 0
-; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[INC]], i32 0
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 [[RET]]
}
define i32 @test_simplify15(i64 %x) {
-; CHECK-FFS-LABEL: @test_simplify15(
+; GENERIC-LABEL: @test_simplify15(
+; GENERIC-NEXT: [[RET:%.*]] = call i32 @ffsll(i64 %x)
+; GENERIC-NEXT: ret i32 [[RET]]
+;
+; TARGET-LABEL: @test_simplify15(
+; TARGET-NEXT: [[CTTZ:%.*]] = call i64 @llvm.cttz.i64(i64 %x, i1 true)
+; TARGET-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[CTTZ]], 1
+; TARGET-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
+; TARGET-NEXT: [[TMP3:%.*]] = icmp ne i64 %x, 0
+; TARGET-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 [[TMP2]], i32 0
+; TARGET-NEXT: ret i32 [[TMP4]]
+;
%ret = call i32 @ffsll(i64 %x)
-; CHECK-FFS-NEXT: [[CTTZ:%[a-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %x, i1 true)
-; CHECK-FFS-NEXT: [[INC:%[a-z0-9]+]] = add nuw nsw i64 [[CTTZ]], 1
-; CHECK-FFS-NEXT: [[TRUNC:%[a-z0-9]+]] = trunc i64 [[INC]] to i32
-; CHECK-FFS-NEXT: [[CMP:%[a-z0-9]+]] = icmp ne i64 %x, 0
-; CHECK-FFS-NEXT: [[RET:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[TRUNC]], i32 0
ret i32 %ret
-; CHECK-FFS-NEXT: ret i32 [[RET]]
}
+
diff --git a/test/Transforms/InstCombine/lshr.ll b/test/Transforms/InstCombine/lshr.ll
index 71b25177162b..4cdcb98f730c 100644
--- a/test/Transforms/InstCombine/lshr.ll
+++ b/test/Transforms/InstCombine/lshr.ll
@@ -122,10 +122,19 @@ define <2 x i8> @bool_zext_splat(<2 x i1> %x) {
ret <2 x i8> %hibit
}
-; FIXME: The replicated sign bits are all that's left. This could be ashr+zext.
-
-define i16 @smear_sign_and_widen(i4 %x) {
+define i32 @smear_sign_and_widen(i8 %x) {
; CHECK-LABEL: @smear_sign_and_widen(
+; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 %x, 7
+; CHECK-NEXT: [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32
+; CHECK-NEXT: ret i32 [[HIBIT]]
+;
+ %sext = sext i8 %x to i32
+ %hibit = lshr i32 %sext, 24
+ ret i32 %hibit
+}
+
+define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) {
+; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type(
; CHECK-NEXT: [[SEXT:%.*]] = sext i4 %x to i16
; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12
; CHECK-NEXT: ret i16 [[HIBIT]]
@@ -137,8 +146,8 @@ define i16 @smear_sign_and_widen(i4 %x) {
define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {
; CHECK-LABEL: @smear_sign_and_widen_splat(
-; CHECK-NEXT: [[SEXT:%.*]] = sext <2 x i6> %x to <2 x i8>
-; CHECK-NEXT: [[HIBIT:%.*]] = lshr <2 x i8> [[SEXT]], <i8 2, i8 2>
+; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i6> %x, <i6 2, i6 2>
+; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8>
; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
;
%sext = sext <2 x i6> %x to <2 x i8>
diff --git a/test/Transforms/InstCombine/onehot_merge.ll b/test/Transforms/InstCombine/onehot_merge.ll
index 496d847b5321..47a4ca4b628b 100644
--- a/test/Transforms/InstCombine/onehot_merge.ll
+++ b/test/Transforms/InstCombine/onehot_merge.ll
@@ -33,3 +33,79 @@ bb:
ret i1 %or
}
+; Same as above but with operands commuted one of the ands, but not the other.
+define i1 @foo1_and_commuted(i32 %k, i32 %c1, i32 %c2) {
+; CHECK-LABEL: @foo1_and_commuted(
+; CHECK-NEXT: [[K2:%.*]] = mul i32 [[K:%.*]], [[K]]
+; CHECK-NEXT: [[TMP:%.*]] = shl i32 1, [[C1:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 -2147483648, [[C2:%.*]]
+; CHECK-NEXT: [[TMP0:%.*]] = or i32 [[TMP]], [[TMP4]]
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K2]], [[TMP0]]
+; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], [[TMP0]]
+; CHECK-NEXT: ret i1 [[TMP2]]
+;
+ %k2 = mul i32 %k, %k ; to trick the complexity sorting
+ %tmp = shl i32 1, %c1
+ %tmp4 = lshr i32 -2147483648, %c2
+ %tmp1 = and i32 %k2, %tmp
+ %tmp2 = icmp eq i32 %tmp1, 0
+ %tmp5 = and i32 %tmp4, %k2
+ %tmp6 = icmp eq i32 %tmp5, 0
+ %or = or i1 %tmp2, %tmp6
+ ret i1 %or
+}
+
+define i1 @or_consts(i32 %k, i32 %c1, i32 %c2) {
+; CHECK-LABEL: @or_consts(
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[K:%.*]], 12
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 12
+; CHECK-NEXT: ret i1 [[TMP2]]
+;
+ %tmp1 = and i32 4, %k
+ %tmp2 = icmp ne i32 %tmp1, 0
+ %tmp5 = and i32 8, %k
+ %tmp6 = icmp ne i32 %tmp5, 0
+ %or = and i1 %tmp2, %tmp6
+ ret i1 %or
+}
+
+define i1 @foo1_or(i32 %k, i32 %c1, i32 %c2) {
+; CHECK-LABEL: @foo1_or(
+; CHECK-NEXT: [[TMP:%.*]] = shl i32 1, [[C1:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 -2147483648, [[C2:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP]], [[TMP4]]
+; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[K:%.*]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]]
+; CHECK-NEXT: ret i1 [[TMP3]]
+;
+ %tmp = shl i32 1, %c1
+ %tmp4 = lshr i32 -2147483648, %c2
+ %tmp1 = and i32 %tmp, %k
+ %tmp2 = icmp ne i32 %tmp1, 0
+ %tmp5 = and i32 %tmp4, %k
+ %tmp6 = icmp ne i32 %tmp5, 0
+ %or = and i1 %tmp2, %tmp6
+ ret i1 %or
+}
+
+; Same as above but with operands commuted one of the ors, but not the other.
+define i1 @foo1_or_commuted(i32 %k, i32 %c1, i32 %c2) {
+; CHECK-LABEL: @foo1_or_commuted(
+; CHECK-NEXT: [[K2:%.*]] = mul i32 [[K:%.*]], [[K]]
+; CHECK-NEXT: [[TMP:%.*]] = shl i32 1, [[C1:%.*]]
+; CHECK-NEXT: [[TMP4:%.*]] = lshr i32 -2147483648, [[C2:%.*]]
+; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[TMP]], [[TMP4]]
+; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[K2]], [[TMP1]]
+; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], [[TMP1]]
+; CHECK-NEXT: ret i1 [[TMP3]]
+;
+ %k2 = mul i32 %k, %k ; to trick the complexity sorting
+ %tmp = shl i32 1, %c1
+ %tmp4 = lshr i32 -2147483648, %c2
+ %tmp1 = and i32 %k2, %tmp
+ %tmp2 = icmp ne i32 %tmp1, 0
+ %tmp5 = and i32 %tmp4, %k2
+ %tmp6 = icmp ne i32 %tmp5, 0
+ %or = and i1 %tmp2, %tmp6
+ ret i1 %or
+}
diff --git a/test/Transforms/InstCombine/or-xor.ll b/test/Transforms/InstCombine/or-xor.ll
index f2bc290d79a4..485f9612376a 100644
--- a/test/Transforms/InstCombine/or-xor.ll
+++ b/test/Transforms/InstCombine/or-xor.ll
@@ -114,6 +114,17 @@ define i32 @test10(i32 %A, i32 %B) {
ret i32 %or
}
+define i32 @test10_commuted(i32 %A, i32 %B) {
+; CHECK-LABEL: @test10_commuted(
+; CHECK-NEXT: ret i32 -1
+;
+ %xor1 = xor i32 %B, %A
+ %not = xor i32 %A, -1
+ %xor2 = xor i32 %not, %B
+ %or = or i32 %xor2, %xor1
+ ret i32 %or
+}
+
; (x | y) & ((~x) ^ y) -> (x & y)
define i32 @test11(i32 %x, i32 %y) {
; CHECK-LABEL: @test11(
@@ -300,3 +311,36 @@ define i8 @or_xor_or(i8 %x) {
ret i8 %or2
}
+define i8 @test17(i8 %A, i8 %B) {
+; CHECK-LABEL: @test17(
+; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33
+; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]]
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR1]], [[XOR2]]
+; CHECK-NEXT: [[RES:%.*]] = mul i8 [[OR]], [[XOR2]]
+; CHECK-NEXT: ret i8 [[RES]]
+;
+ %xor1 = xor i8 %B, %A
+ %not = xor i8 %A, 33
+ %xor2 = xor i8 %not, %B
+ %or = or i8 %xor1, %xor2
+ %res = mul i8 %or, %xor2 ; to increase the use count for the xor
+ ret i8 %res
+}
+
+define i8 @test18(i8 %A, i8 %B) {
+; CHECK-LABEL: @test18(
+; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33
+; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]]
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[XOR2]], [[XOR1]]
+; CHECK-NEXT: [[RES:%.*]] = mul i8 [[OR]], [[XOR2]]
+; CHECK-NEXT: ret i8 [[RES]]
+;
+ %xor1 = xor i8 %B, %A
+ %not = xor i8 %A, 33
+ %xor2 = xor i8 %not, %B
+ %or = or i8 %xor2, %xor1
+ %res = mul i8 %or, %xor2 ; to increase the use count for the xor
+ ret i8 %res
+}
diff --git a/test/Transforms/InstCombine/select-with-bitwise-ops.ll b/test/Transforms/InstCombine/select-with-bitwise-ops.ll
index 68b73af21a8d..faeb4e046aca 100644
--- a/test/Transforms/InstCombine/select-with-bitwise-ops.ll
+++ b/test/Transforms/InstCombine/select-with-bitwise-ops.ll
@@ -1,6 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
+target datalayout = "n8:16:32:64"
+
define i32 @select_icmp_eq_and_1_0_or_2(i32 %x, i32 %y) {
; CHECK-LABEL: @select_icmp_eq_and_1_0_or_2(
; CHECK-NEXT: [[AND:%.*]] = shl i32 %x, 1
@@ -295,3 +297,269 @@ define i32 @test67(i16 %x) {
ret i32 %3
}
+define i32 @test68(i32 %x, i32 %y) {
+; CHECK-LABEL: @test68(
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[TMP1]], -1
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %and = and i32 %x, 128
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, 2
+ %select = select i1 %cmp, i32 %y, i32 %or
+ ret i32 %select
+}
+
+define i32 @test69(i32 %x, i32 %y) {
+; CHECK-LABEL: @test69(
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i8
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[TMP1]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2
+; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], i32 [[Y]], i32 [[OR]]
+; CHECK-NEXT: ret i32 [[SELECT]]
+;
+ %and = and i32 %x, 128
+ %cmp = icmp ne i32 %and, 0
+ %or = or i32 %y, 2
+ %select = select i1 %cmp, i32 %y, i32 %or
+ ret i32 %select
+}
+
+define i32 @shift_no_xor_multiuse_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @shift_no_xor_multiuse_or(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2
+; CHECK-NEXT: [[AND:%.*]] = shl i32 [[X:%.*]], 1
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 1
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, 2
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %res = mul i32 %select, %or ; to bump up use count of the Or
+ ret i32 %res
+}
+
+define i32 @no_shift_no_xor_multiuse_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @no_shift_no_xor_multiuse_or(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096
+; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], [[Y]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP1]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, 4096
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %res = mul i32 %select, %or ; to bump up use count of the Or
+ ret i32 %res
+}
+
+define i32 @no_shift_xor_multiuse_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @no_shift_xor_multiuse_or(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], 4096
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp ne i32 0, %and
+ %or = or i32 %y, 4096
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %res = mul i32 %select, %or ; to bump up use count of the Or
+ ret i32 %res
+}
+
+; TODO this increased the number of instructions
+define i32 @shift_xor_multiuse_or(i32 %x, i32 %y) {
+; CHECK-LABEL: @shift_xor_multiuse_or(
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2048
+; CHECK-NEXT: [[AND:%.*]] = lshr i32 [[X:%.*]], 1
+; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[AND]], 2048
+; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], 2048
+; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP2]], [[Y]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP3]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp ne i32 0, %and
+ %or = or i32 %y, 2048
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %res = mul i32 %select, %or ; to bump up use count of the Or
+ ret i32 %res
+}
+
+define i32 @shift_no_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @shift_no_xor_multiuse_cmp(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i32 [[AND]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 1
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, 2
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ ret i32 %res
+}
+
+define i32 @no_shift_no_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @no_shift_no_xor_multiuse_cmp(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], [[Y:%.*]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP1]], [[SELECT2]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, 4096
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ ret i32 %res
+}
+
+define i32 @no_shift_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @no_shift_xor_multiuse_cmp(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], 4096
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y:%.*]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp ne i32 0, %and
+ %or = or i32 %y, 4096
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ ret i32 %res
+}
+
+; TODO this increased the number of instructions
+define i32 @shift_xor_multiuse_cmp(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @shift_xor_multiuse_cmp(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
+; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[AND]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], 2048
+; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP2]], [[Y:%.*]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP3]], [[SELECT2]]
+; CHECK-NEXT: ret i32 [[RES]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp ne i32 0, %and
+ %or = or i32 %y, 2048
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ ret i32 %res
+}
+
+; TODO this increased the number of instructions
+define i32 @shift_no_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @shift_no_xor_multiuse_cmp_or(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 1
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2
+; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i32 [[AND]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]]
+; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES2]]
+;
+ %and = and i32 %x, 1
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, 2
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ %res2 = mul i32 %res, %or ; to bump up the use count of the or
+ ret i32 %res2
+}
+
+define i32 @no_shift_no_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @no_shift_no_xor_multiuse_cmp_or(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096
+; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], [[Y]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP1]], [[SELECT2]]
+; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES2]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp eq i32 %and, 0
+ %or = or i32 %y, 4096
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ %res2 = mul i32 %res, %or ; to bump up the use count of the or
+ ret i32 %res2
+}
+
+; TODO this increased the number of instructions
+define i32 @no_shift_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @no_shift_xor_multiuse_cmp_or(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 4096
+; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[AND]], 4096
+; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], [[Y]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP2]], [[SELECT2]]
+; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES2]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp ne i32 0, %and
+ %or = or i32 %y, 4096
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ %res2 = mul i32 %res, %or ; to bump up the use count of the or
+ ret i32 %res2
+}
+
+; TODO this increased the number of instructions
+define i32 @shift_xor_multiuse_cmp_or(i32 %x, i32 %y, i32 %z, i32 %w) {
+; CHECK-LABEL: @shift_xor_multiuse_cmp_or(
+; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 4096
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[AND]], 0
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], 2048
+; CHECK-NEXT: [[TMP1:%.*]] = lshr exact i32 [[AND]], 1
+; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[TMP1]], 2048
+; CHECK-NEXT: [[TMP3:%.*]] = or i32 [[TMP2]], [[Y]]
+; CHECK-NEXT: [[SELECT2:%.*]] = select i1 [[CMP]], i32 [[Z:%.*]], i32 [[W:%.*]]
+; CHECK-NEXT: [[RES:%.*]] = mul i32 [[TMP3]], [[SELECT2]]
+; CHECK-NEXT: [[RES2:%.*]] = mul i32 [[RES]], [[OR]]
+; CHECK-NEXT: ret i32 [[RES2]]
+;
+ %and = and i32 %x, 4096
+ %cmp = icmp ne i32 0, %and
+ %or = or i32 %y, 2048
+ %select = select i1 %cmp, i32 %y, i32 %or
+ %select2 = select i1 %cmp, i32 %z, i32 %w ; to bump up use count of the cmp
+ %res = mul i32 %select, %select2
+ %res2 = mul i32 %res, %or ; to bump up the use count of the or
+ ret i32 %res2
+}
diff --git a/test/Transforms/InstCombine/shift.ll b/test/Transforms/InstCombine/shift.ll
index ce8e2fcd38b9..68bbf35d1e65 100644
--- a/test/Transforms/InstCombine/shift.ll
+++ b/test/Transforms/InstCombine/shift.ll
@@ -1306,3 +1306,13 @@ define <2 x i8> @lshr_demanded_bits_splat(<2 x i8> %x) {
ret <2 x i8> %shr
}
+; Make sure known bits works correctly with non power of 2 bit widths.
+define i7 @test65(i7 %a, i7 %b) {
+; CHECK-LABEL: @test65(
+; CHECK-NEXT: ret i7 0
+;
+ %shiftamt = and i7 %b, 6 ; this ensures the shift amount is even and less than the bit width.
+ %x = lshr i7 42, %shiftamt ; 42 has a zero in every even numbered bit and a one in every odd bit.
+ %y = and i7 %x, 1 ; this extracts the lsb which should be 0 because we shifted an even number of bits and all even bits of the shift input are 0.
+ ret i7 %y
+}
diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll
index 3afbf632f6e1..49e6b999fbce 100644
--- a/test/Transforms/InstCombine/xor2.ll
+++ b/test/Transforms/InstCombine/xor2.ll
@@ -325,3 +325,36 @@ define i32 @test14(i32 %a, i32 %b, i32 %c) {
ret i32 %xor
}
+define i8 @test15(i8 %A, i8 %B) {
+; CHECK-LABEL: @test15(
+; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33
+; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]]
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR1]], [[XOR2]]
+; CHECK-NEXT: [[RES:%.*]] = mul i8 [[AND]], [[XOR2]]
+; CHECK-NEXT: ret i8 [[RES]]
+;
+ %xor1 = xor i8 %B, %A
+ %not = xor i8 %A, 33
+ %xor2 = xor i8 %not, %B
+ %and = and i8 %xor1, %xor2
+ %res = mul i8 %and, %xor2 ; to increase the use count for the xor
+ ret i8 %res
+}
+
+define i8 @test16(i8 %A, i8 %B) {
+; CHECK-LABEL: @test16(
+; CHECK-NEXT: [[XOR1:%.*]] = xor i8 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[A]], 33
+; CHECK-NEXT: [[XOR2:%.*]] = xor i8 [[NOT]], [[B]]
+; CHECK-NEXT: [[AND:%.*]] = and i8 [[XOR2]], [[XOR1]]
+; CHECK-NEXT: [[RES:%.*]] = mul i8 [[AND]], [[XOR2]]
+; CHECK-NEXT: ret i8 [[RES]]
+;
+ %xor1 = xor i8 %B, %A
+ %not = xor i8 %A, 33
+ %xor2 = xor i8 %not, %B
+ %and = and i8 %xor2, %xor1
+ %res = mul i8 %and, %xor2 ; to increase the use count for the xor
+ ret i8 %res
+}
diff --git a/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll b/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll
index ec93847178b5..d52378b864ff 100644
--- a/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll
+++ b/test/Transforms/LoopIdiom/X86/unordered-atomic-memcpy.ll
@@ -5,7 +5,7 @@ target triple = "x86_64-unknown-linux-gnu"
;; memcpy.atomic formation (atomic load & store)
define void @test1(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test1(
-; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1)
+; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1)
; CHECK-NOT: store
; CHECK: ret void
bb.nph:
@@ -30,7 +30,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation (atomic store, normal load)
define void @test2(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test2(
-; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1)
+; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1)
; CHECK-NOT: store
; CHECK: ret void
bb.nph:
@@ -55,7 +55,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (atomic store, normal load w/ no align)
define void @test2b(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test2b(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -80,7 +80,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (atomic store, normal load w/ bad align)
define void @test2c(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test2c(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -105,7 +105,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (atomic store w/ bad align, normal load)
define void @test2d(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test2d(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -131,7 +131,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation (normal store, atomic load)
define void @test3(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test3(
-; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1)
+; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %Dest, i8* align 1 %Base, i64 %Size, i32 1)
; CHECK-NOT: store
; CHECK: ret void
bb.nph:
@@ -156,7 +156,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (normal store w/ no align, atomic load)
define void @test3b(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test3b(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -181,7 +181,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (normal store, atomic load w/ bad align)
define void @test3c(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test3c(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -206,7 +206,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (normal store w/ bad align, atomic load)
define void @test3d(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test3d(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -232,7 +232,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (atomic load, ordered-atomic store)
define void @test4(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test4(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -257,7 +257,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (ordered-atomic load, unordered-atomic store)
define void @test5(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test5(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
@@ -282,7 +282,8 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation (atomic load & store) -- element size 2
define void @test6(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test6(
-; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 2 %Dest{{[0-9]*}}, i8* align 2 %Base{{[0-9]*}}, i64 %Size, i32 2)
+; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 1
+; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 2 %Dest{{[0-9]*}}, i8* align 2 %Base{{[0-9]*}}, i64 [[Sz]], i32 2)
; CHECK-NOT: store
; CHECK: ret void
bb.nph:
@@ -307,7 +308,8 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation (atomic load & store) -- element size 4
define void @test7(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test7(
-; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %Dest{{[0-9]*}}, i8* align 4 %Base{{[0-9]*}}, i64 %Size, i32 4)
+; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 2
+; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 4 %Dest{{[0-9]*}}, i8* align 4 %Base{{[0-9]*}}, i64 [[Sz]], i32 4)
; CHECK-NOT: store
; CHECK: ret void
bb.nph:
@@ -332,7 +334,8 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation (atomic load & store) -- element size 8
define void @test8(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test8(
-; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 8 %Dest{{[0-9]*}}, i8* align 8 %Base{{[0-9]*}}, i64 %Size, i32 8)
+; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 3
+; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 8 %Dest{{[0-9]*}}, i8* align 8 %Base{{[0-9]*}}, i64 [[Sz]], i32 8)
; CHECK-NOT: store
; CHECK: ret void
bb.nph:
@@ -357,7 +360,8 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (atomic load & store) -- element size 16
define void @test9(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test9(
-; CHECK: call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 16 %Dest{{[0-9]*}}, i8* align 16 %Base{{[0-9]*}}, i64 %Size, i32 16)
+; CHECK: [[Sz:%[0-9]+]] = shl i64 %Size, 4
+; CHECK: call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 16 %Dest{{[0-9]*}}, i8* align 16 %Base{{[0-9]*}}, i64 [[Sz]], i32 16)
; CHECK-NOT: store
; CHECK: ret void
bb.nph:
@@ -382,7 +386,7 @@ for.end: ; preds = %for.body, %entry
;; memcpy.atomic formation rejection (atomic load & store) -- element size 32
define void @test10(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test10(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
diff --git a/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll b/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll
index b2528f1c2457..341a7a0baebf 100644
--- a/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll
+++ b/test/Transforms/LoopIdiom/unordered-atomic-memcpy-noarch.ll
@@ -5,7 +5,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
;; Will not create call due to a max element size of 0
define void @test1(i64 %Size) nounwind ssp {
; CHECK-LABEL: @test1(
-; CHECK-NOT: call void @llvm.memcpy.element.atomic
+; CHECK-NOT: call void @llvm.memcpy.element.unordered.atomic
; CHECK: store
; CHECK: ret void
bb.nph:
diff --git a/test/Transforms/LowerTypeTests/Inputs/import-icall.yaml b/test/Transforms/LowerTypeTests/Inputs/import-icall.yaml
new file mode 100644
index 000000000000..17b634acd0e1
--- /dev/null
+++ b/test/Transforms/LowerTypeTests/Inputs/import-icall.yaml
@@ -0,0 +1,19 @@
+---
+TypeIdMap:
+ typeid1:
+ TTRes:
+ Kind: AllOnes
+ SizeM1BitWidth: 7
+ typeid2:
+ TTRes:
+ Kind: Single
+ SizeM1BitWidth: 0
+WithGlobalValueDeadStripping: false
+CfiFunctionDefs:
+ - local_a
+ - local_b
+ - does_not_exist
+CfiFunctionDecls:
+ - external
+ - external_weak
+...
diff --git a/test/Transforms/LowerTypeTests/export-icall.ll b/test/Transforms/LowerTypeTests/export-icall.ll
new file mode 100644
index 000000000000..ad3604899306
--- /dev/null
+++ b/test/Transforms/LowerTypeTests/export-icall.ll
@@ -0,0 +1,70 @@
+; RUN: opt -S -lowertypetests -lowertypetests-summary-action=export -lowertypetests-read-summary=%S/Inputs/use-typeid1-typeid2.yaml -lowertypetests-write-summary=%t < %s | FileCheck %s
+; RUN: FileCheck --check-prefix=SUMMARY %s < %t
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @h(i8 %x) !type !2 {
+ ret void
+}
+
+declare !type !8 void @f(i32 %x)
+
+!cfi.functions = !{!0, !1, !3, !4, !5, !6}
+
+; declaration of @h with a different type is ignored
+!0 = !{!"h", i8 1, !7}
+
+; extern_weak declaration of @h with a different type is ignored as well
+!1 = !{!"h", i8 2, !8}
+!2 = !{i64 0, !"typeid1"}
+
+; definition of @f replaces types on the IR declaration above
+!3 = !{!"f", i8 0, !2}
+!4 = !{!"external", i8 1, !2}
+!5 = !{!"external_weak", i8 2, !2}
+!6 = !{!"g", i8 0, !7}
+!7 = !{i64 0, !"typeid2"}
+!8 = !{i64 0, !"typeid3"}
+
+
+; CHECK-DAG: @__typeid_typeid1_global_addr = hidden alias i8, bitcast (void ()* [[JT1:.*]] to i8*)
+; CHECK-DAG: @__typeid_typeid1_align = hidden alias i8, inttoptr (i8 3 to i8*)
+; CHECK-DAG: @__typeid_typeid1_size_m1 = hidden alias i8, inttoptr (i64 3 to i8*)
+
+; CHECK-DAG: @h = alias void (i8), bitcast (void ()* [[JT1]] to void (i8)*)
+; CHECK-DAG: @f = alias void (i32), {{.*}}getelementptr {{.*}}void ()* [[JT1]]
+; CHECK-DAG: @external.cfi_jt = hidden alias void (), {{.*}}getelementptr {{.*}}void ()* [[JT1]]
+; CHECK-DAG: @external_weak.cfi_jt = hidden alias void (), {{.*}}getelementptr {{.*}}void ()* [[JT1]]
+
+; CHECK-DAG: @__typeid_typeid2_global_addr = hidden alias i8, bitcast (void ()* [[JT2:.*]] to i8*)
+
+; CHECK-DAG: @g = alias void (), void ()* [[JT2]]
+
+; CHECK-DAG: define internal void @h.cfi(i8 {{.*}}) !type !{{.*}}
+; CHECK-DAG: declare !type !{{.*}} void @external()
+; CHECK-DAG: declare !type !{{.*}} void @external_weak()
+; CHECK-DAG: declare !type !{{.*}} void @f.cfi(i32)
+; CHECK-DAG: declare !type !{{.*}} void @g.cfi()
+
+
+; SUMMARY: TypeIdMap:
+; SUMMARY-NEXT: typeid1:
+; SUMMARY-NEXT: TTRes:
+; SUMMARY-NEXT: Kind: AllOnes
+; SUMMARY-NEXT: SizeM1BitWidth: 7
+; SUMMARY-NEXT: WPDRes:
+; SUMMARY-NEXT: typeid2:
+; SUMMARY-NEXT: TTRes:
+; SUMMARY-NEXT: Kind: Single
+; SUMMARY-NEXT: SizeM1BitWidth: 0
+; SUMMARY-NEXT: WPDRes:
+
+; SUMMARY: CfiFunctionDefs:
+; SUMMARY-NEXT: - f
+; SUMMARY-NEXT: - g
+; SUMMARY-NEXT: - h
+; SUMMARY-NEXT: CfiFunctionDecls:
+; SUMMARY-NEXT: - external
+; SUMMARY-NEXT: - external_weak
+; SUMMARY-NEXT: ...
diff --git a/test/Transforms/LowerTypeTests/import-icall.ll b/test/Transforms/LowerTypeTests/import-icall.ll
new file mode 100644
index 000000000000..ddeb7fb5c9a2
--- /dev/null
+++ b/test/Transforms/LowerTypeTests/import-icall.ll
@@ -0,0 +1,40 @@
+; RUN: opt -S -lowertypetests -lowertypetests-summary-action=import -lowertypetests-read-summary=%S/Inputs/import-icall.yaml < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define i8 @local_a() {
+ call void @external()
+ call void @external_weak()
+ ret i8 1
+}
+
+define internal i8 @local_b() {
+ %x = call i8 @local_a()
+ ret i8 %x
+}
+
+define i8 @use_b() {
+ %x = call i8 @local_b()
+ ret i8 %x
+}
+
+
+declare void @external()
+declare extern_weak void @external_weak()
+
+; CHECK: define hidden i8 @local_a.cfi() {
+; CHECK-NEXT: call void @external.cfi_jt()
+; CHECK-NEXT: call void select (i1 icmp ne (void ()* @external_weak, void ()* null), void ()* @external_weak.cfi_jt, void ()* null)()
+; CHECK-NEXT: ret i8 1
+; CHECK-NEXT: }
+
+; internal @local_b is not the same function as "local_b" in the summary.
+; CHECK: define internal i8 @local_b() {
+; CHECK-NEXT: call i8 @local_a()
+
+; CHECK: declare void @external()
+; CHECK: declare extern_weak void @external_weak()
+; CHECK: declare i8 @local_a()
+; CHECK: declare hidden void @external.cfi_jt()
+; CHECK: declare hidden void @external_weak.cfi_jt()
diff --git a/test/Transforms/PGOProfile/memop_size_opt.ll b/test/Transforms/PGOProfile/memop_size_opt.ll
index 19a2b7ed293b..e11f235a48e7 100644
--- a/test/Transforms/PGOProfile/memop_size_opt.ll
+++ b/test/Transforms/PGOProfile/memop_size_opt.ll
@@ -38,7 +38,7 @@ for.body3:
; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i32 1, i1 false)
; MEMOP_OPT: br label %[[MERGE_LABEL:.*]]
; MEMOP_OPT: [[DEFAULT_LABEL]]:
-; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i32 1, i1 false){{[[:space:]]}}
+; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %conv, i32 1, i1 false), !prof [[NEWVP:![0-9]+]]
; MEMOP_OPT: br label %[[MERGE_LABEL]]
; MEMOP_OPT: [[MERGE_LABEL]]:
; MEMOP_OPT: switch i64 %conv, label %[[DEFAULT_LABEL2:.*]] [
@@ -48,11 +48,16 @@ for.body3:
; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 1, i32 1, i1 false)
; MEMOP_OPT: br label %[[MERGE_LABEL2:.*]]
; MEMOP_OPT: [[DEFAULT_LABEL2]]:
-; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 %conv, i32 1, i1 false){{[[:space:]]}}
+; MEMOP_OPT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst2, i8* %src2, i64 %conv, i32 1, i1 false), !prof [[NEWVP]]
; MEMOP_OPT: br label %[[MERGE_LABEL2]]
; MEMOP_OPT: [[MERGE_LABEL2]]:
; MEMOP_OPT: br label %for.inc
; MEMOP_OPT: [[SWITCH_BW]] = !{!"branch_weights", i32 457, i32 99}
+; Should be 457 total left (original total count 556, minus 99 from specialized
+; value 1, which is removed from VP array. Also, we only end up with 5 total
+; values, since the default max number of promotions is 5 and therefore
+; the rest of the values are ignored when extracting the VP metadata.
+; MEMOP_OPT: [[NEWVP]] = !{!"VP", i32 1, i64 457, i64 2, i64 88, i64 3, i64 77, i64 9, i64 72, i64 4, i64 66}
for.inc:
%inc = add nsw i32 %j.0, 1
diff --git a/test/Transforms/RewriteStatepointsForGC/drop-invalid-metadata.ll b/test/Transforms/RewriteStatepointsForGC/drop-invalid-metadata.ll
new file mode 100644
index 000000000000..105afa9def5c
--- /dev/null
+++ b/test/Transforms/RewriteStatepointsForGC/drop-invalid-metadata.ll
@@ -0,0 +1,92 @@
+; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s
+
+; This test checks that metadata that's invalid after RS4GC is dropped.
+; We can miscompile if optimizations scheduled after RS4GC uses the
+; metadata that's infact invalid.
+
+declare void @bar()
+
+declare void @baz(i32)
+; Confirm that loadedval instruction does not contain invariant.load metadata.
+; but contains the range metadata.
+; Since loadedval is not marked invariant, it will prevent incorrectly sinking
+; %loadedval in LICM and avoid creation of an unrelocated use of %baseaddr.
+define void @test_invariant_load() gc "statepoint-example" {
+; CHECK-LABEL: @test_invariant_load
+; CHECK: %loadedval = load i32, i32 addrspace(1)* %baseaddr, align 8, !range !0
+bb:
+ br label %outerloopHdr
+
+outerloopHdr: ; preds = %bb6, %bb
+ %baseaddr = phi i32 addrspace(1)* [ undef, %bb ], [ %tmp4, %bb6 ]
+; LICM may sink this load to exit block after RS4GC because it's tagged invariant.
+ %loadedval = load i32, i32 addrspace(1)* %baseaddr, align 8, !range !0, !invariant.load !1
+ br label %innerloopHdr
+
+innerloopHdr: ; preds = %innerlooplatch, %outerloopHdr
+ %tmp4 = phi i32 addrspace(1)* [ %baseaddr, %outerloopHdr ], [ %gep, %innerlooplatch ]
+ br label %innermostloophdr
+
+innermostloophdr: ; preds = %bb6, %innerloopHdr
+ br i1 undef, label %exitblock, label %bb6
+
+bb6: ; preds = %innermostloophdr
+ switch i32 undef, label %innermostloophdr [
+ i32 0, label %outerloopHdr
+ i32 1, label %innerlooplatch
+ ]
+
+innerlooplatch: ; preds = %bb6
+ call void @bar()
+ %gep = getelementptr inbounds i32, i32 addrspace(1)* %tmp4, i64 8
+ br label %innerloopHdr
+
+exitblock: ; preds = %innermostloophdr
+ %tmp13 = add i32 42, %loadedval
+ call void @baz(i32 %tmp13)
+ unreachable
+}
+
+; drop the noalias metadata.
+define void @test_noalias(i32 %x, i32 addrspace(1)* %p, i32 addrspace(1)* %q) gc "statepoint-example" {
+; CHECK-LABEL: test_noalias
+; CHECK: %y = load i32, i32 addrspace(1)* %q, align 16
+; CHECK: gc.statepoint
+; CHECK: %p.relocated
+; CHECK-NEXT: %p.relocated.casted = bitcast i8 addrspace(1)* %p.relocated to i32 addrspace(1)*
+; CHECK-NEXT: store i32 %x, i32 addrspace(1)* %p.relocated.casted, align 16
+entry:
+ %y = load i32, i32 addrspace(1)* %q, align 16, !noalias !3
+ call void @baz(i32 %x)
+ store i32 %x, i32 addrspace(1)* %p, align 16, !noalias !4
+ ret void
+}
+
+; drop the dereferenceable metadata
+define void @test_dereferenceable(i32 addrspace(1)* addrspace(1)* %p, i32 %x, i32 addrspace(1)* %q) gc "statepoint-example" {
+; CHECK-LABEL: test_dereferenceable
+; CHECK: %v1 = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %p
+; CHECK-NEXT: %v2 = load i32, i32 addrspace(1)* %v1
+; CHECK: gc.statepoint
+ %v1 = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %p, !dereferenceable !5
+ %v2 = load i32, i32 addrspace(1)* %v1
+ call void @baz(i32 %x)
+ store i32 %v2, i32 addrspace(1)* %q, align 16
+ ret void
+}
+
+declare token @llvm.experimental.gc.statepoint.p0f_isVoidi32f(i64, i32, void (i32)*, i32, i32, ...)
+
+; Function Attrs: nounwind readonly
+declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) #0
+
+declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
+
+attributes #0 = { nounwind readonly }
+
+!0 = !{i32 0, i32 2147483647}
+!1 = !{}
+!2 = !{i32 10, i32 1}
+!3 = !{!3}
+!4 = !{!4}
+!5 = !{i64 8}
diff --git a/test/Transforms/SLPVectorizer/X86/arith-add.ll b/test/Transforms/SLPVectorizer/X86/arith-add.ll
index 0266758b27d2..22b2c7422933 100644
--- a/test/Transforms/SLPVectorizer/X86/arith-add.ll
+++ b/test/Transforms/SLPVectorizer/X86/arith-add.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE
+; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX1
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX2
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512 --check-prefix=AVX512F
@@ -38,6 +39,25 @@ define void @add_v8i64() {
; SSE-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8
; SSE-NEXT: ret void
;
+; SLM-LABEL: @add_v8i64(
+; SLM-NEXT: [[TMP1:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @a64 to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP2:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 2) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP4:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 6) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @b64 to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP6:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 2) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 4) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP8:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 6) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP9:%.*]] = add <2 x i64> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = add <2 x i64> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = add <2 x i64> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = add <2 x i64> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <2 x i64> [[TMP9]], <2 x i64>* bitcast ([8 x i64]* @c64 to <2 x i64>*), align 8
+; SLM-NEXT: store <2 x i64> [[TMP10]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 2) to <2 x i64>*), align 8
+; SLM-NEXT: store <2 x i64> [[TMP11]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 4) to <2 x i64>*), align 8
+; SLM-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @add_v8i64(
; AVX-NEXT: [[TMP1:%.*]] = load <4 x i64>, <4 x i64>* bitcast ([8 x i64]* @a64 to <4 x i64>*), align 8
; AVX-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <4 x i64>*), align 8
@@ -111,6 +131,25 @@ define void @add_v16i32() {
; SSE-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4
; SSE-NEXT: ret void
;
+; SLM-LABEL: @add_v16i32(
+; SLM-NEXT: [[TMP1:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @a32 to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @b32 to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP9:%.*]] = add <4 x i32> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = add <4 x i32> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = add <4 x i32> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = add <4 x i32> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <4 x i32> [[TMP9]], <4 x i32>* bitcast ([16 x i32]* @c32 to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP10]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP11]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @add_v16i32(
; AVX-NEXT: [[TMP1:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([16 x i32]* @a32 to <8 x i32>*), align 4
; AVX-NEXT: [[TMP2:%.*]] = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <8 x i32>*), align 4
@@ -216,6 +255,25 @@ define void @add_v32i16() {
; SSE-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2
; SSE-NEXT: ret void
;
+; SLM-LABEL: @add_v32i16(
+; SLM-NEXT: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @a16 to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @b16 to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP9:%.*]] = add <8 x i16> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = add <8 x i16> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = add <8 x i16> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = add <8 x i16> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <8 x i16> [[TMP9]], <8 x i16>* bitcast ([32 x i16]* @c16 to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP10]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP11]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @add_v32i16(
; AVX-NEXT: [[TMP1:%.*]] = load <16 x i16>, <16 x i16>* bitcast ([32 x i16]* @a16 to <16 x i16>*), align 2
; AVX-NEXT: [[TMP2:%.*]] = load <16 x i16>, <16 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <16 x i16>*), align 2
diff --git a/test/Transforms/SLPVectorizer/X86/arith-fp.ll b/test/Transforms/SLPVectorizer/X86/arith-fp.ll
index e00ed849ee4b..119cf594c905 100644
--- a/test/Transforms/SLPVectorizer/X86/arith-fp.ll
+++ b/test/Transforms/SLPVectorizer/X86/arith-fp.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE
+; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=skx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX
@@ -69,13 +70,32 @@ define <2 x double> @buildvector_mul_2f64(<2 x double> %a, <2 x double> %b) {
}
define <2 x double> @buildvector_div_2f64(<2 x double> %a, <2 x double> %b) {
-; CHECK-LABEL: @buildvector_div_2f64(
-; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i32 0
-; CHECK-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[TMP2]], i32 0
-; CHECK-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
-; CHECK-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[TMP3]], i32 1
-; CHECK-NEXT: ret <2 x double> [[R1]]
+; SSE-LABEL: @buildvector_div_2f64(
+; SSE-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[A:%.*]], [[B:%.*]]
+; SSE-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i32 0
+; SSE-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[TMP2]], i32 0
+; SSE-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
+; SSE-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[TMP3]], i32 1
+; SSE-NEXT: ret <2 x double> [[R1]]
+;
+; SLM-LABEL: @buildvector_div_2f64(
+; SLM-NEXT: [[A0:%.*]] = extractelement <2 x double> [[A:%.*]], i32 0
+; SLM-NEXT: [[A1:%.*]] = extractelement <2 x double> [[A]], i32 1
+; SLM-NEXT: [[B0:%.*]] = extractelement <2 x double> [[B:%.*]], i32 0
+; SLM-NEXT: [[B1:%.*]] = extractelement <2 x double> [[B]], i32 1
+; SLM-NEXT: [[C0:%.*]] = fdiv double [[A0]], [[B0]]
+; SLM-NEXT: [[C1:%.*]] = fdiv double [[A1]], [[B1]]
+; SLM-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[C0]], i32 0
+; SLM-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[C1]], i32 1
+; SLM-NEXT: ret <2 x double> [[R1]]
+;
+; AVX-LABEL: @buildvector_div_2f64(
+; AVX-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[A:%.*]], [[B:%.*]]
+; AVX-NEXT: [[TMP2:%.*]] = extractelement <2 x double> [[TMP1]], i32 0
+; AVX-NEXT: [[R0:%.*]] = insertelement <2 x double> undef, double [[TMP2]], i32 0
+; AVX-NEXT: [[TMP3:%.*]] = extractelement <2 x double> [[TMP1]], i32 1
+; AVX-NEXT: [[R1:%.*]] = insertelement <2 x double> [[R0]], double [[TMP3]], i32 1
+; AVX-NEXT: ret <2 x double> [[R1]]
;
%a0 = extractelement <2 x double> %a, i32 0
%a1 = extractelement <2 x double> %a, i32 1
@@ -317,17 +337,48 @@ define <4 x double> @buildvector_mul_4f64(<4 x double> %a, <4 x double> %b) {
}
define <4 x double> @buildvector_div_4f64(<4 x double> %a, <4 x double> %b) {
-; CHECK-LABEL: @buildvector_div_4f64(
-; CHECK-NEXT: [[TMP1:%.*]] = fdiv <4 x double> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP1]], i32 0
-; CHECK-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[TMP2]], i32 0
-; CHECK-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 1
-; CHECK-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[TMP3]], i32 1
-; CHECK-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP1]], i32 2
-; CHECK-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[TMP4]], i32 2
-; CHECK-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 3
-; CHECK-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[TMP5]], i32 3
-; CHECK-NEXT: ret <4 x double> [[R3]]
+; SSE-LABEL: @buildvector_div_4f64(
+; SSE-NEXT: [[TMP1:%.*]] = fdiv <4 x double> [[A:%.*]], [[B:%.*]]
+; SSE-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP1]], i32 0
+; SSE-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[TMP2]], i32 0
+; SSE-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 1
+; SSE-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[TMP3]], i32 1
+; SSE-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP1]], i32 2
+; SSE-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[TMP4]], i32 2
+; SSE-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 3
+; SSE-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[TMP5]], i32 3
+; SSE-NEXT: ret <4 x double> [[R3]]
+;
+; SLM-LABEL: @buildvector_div_4f64(
+; SLM-NEXT: [[A0:%.*]] = extractelement <4 x double> [[A:%.*]], i32 0
+; SLM-NEXT: [[A1:%.*]] = extractelement <4 x double> [[A]], i32 1
+; SLM-NEXT: [[A2:%.*]] = extractelement <4 x double> [[A]], i32 2
+; SLM-NEXT: [[A3:%.*]] = extractelement <4 x double> [[A]], i32 3
+; SLM-NEXT: [[B0:%.*]] = extractelement <4 x double> [[B:%.*]], i32 0
+; SLM-NEXT: [[B1:%.*]] = extractelement <4 x double> [[B]], i32 1
+; SLM-NEXT: [[B2:%.*]] = extractelement <4 x double> [[B]], i32 2
+; SLM-NEXT: [[B3:%.*]] = extractelement <4 x double> [[B]], i32 3
+; SLM-NEXT: [[C0:%.*]] = fdiv double [[A0]], [[B0]]
+; SLM-NEXT: [[C1:%.*]] = fdiv double [[A1]], [[B1]]
+; SLM-NEXT: [[C2:%.*]] = fdiv double [[A2]], [[B2]]
+; SLM-NEXT: [[C3:%.*]] = fdiv double [[A3]], [[B3]]
+; SLM-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[C0]], i32 0
+; SLM-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[C1]], i32 1
+; SLM-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[C2]], i32 2
+; SLM-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[C3]], i32 3
+; SLM-NEXT: ret <4 x double> [[R3]]
+;
+; AVX-LABEL: @buildvector_div_4f64(
+; AVX-NEXT: [[TMP1:%.*]] = fdiv <4 x double> [[A:%.*]], [[B:%.*]]
+; AVX-NEXT: [[TMP2:%.*]] = extractelement <4 x double> [[TMP1]], i32 0
+; AVX-NEXT: [[R0:%.*]] = insertelement <4 x double> undef, double [[TMP2]], i32 0
+; AVX-NEXT: [[TMP3:%.*]] = extractelement <4 x double> [[TMP1]], i32 1
+; AVX-NEXT: [[R1:%.*]] = insertelement <4 x double> [[R0]], double [[TMP3]], i32 1
+; AVX-NEXT: [[TMP4:%.*]] = extractelement <4 x double> [[TMP1]], i32 2
+; AVX-NEXT: [[R2:%.*]] = insertelement <4 x double> [[R1]], double [[TMP4]], i32 2
+; AVX-NEXT: [[TMP5:%.*]] = extractelement <4 x double> [[TMP1]], i32 3
+; AVX-NEXT: [[R3:%.*]] = insertelement <4 x double> [[R2]], double [[TMP5]], i32 3
+; AVX-NEXT: ret <4 x double> [[R3]]
;
%a0 = extractelement <4 x double> %a, i32 0
%a1 = extractelement <4 x double> %a, i32 1
@@ -745,25 +796,80 @@ define <8 x double> @buildvector_mul_8f64(<8 x double> %a, <8 x double> %b) {
}
define <8 x double> @buildvector_div_8f64(<8 x double> %a, <8 x double> %b) {
-; CHECK-LABEL: @buildvector_div_8f64(
-; CHECK-NEXT: [[TMP1:%.*]] = fdiv <8 x double> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT: [[TMP2:%.*]] = extractelement <8 x double> [[TMP1]], i32 0
-; CHECK-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0
-; CHECK-NEXT: [[TMP3:%.*]] = extractelement <8 x double> [[TMP1]], i32 1
-; CHECK-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[TMP3]], i32 1
-; CHECK-NEXT: [[TMP4:%.*]] = extractelement <8 x double> [[TMP1]], i32 2
-; CHECK-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[TMP4]], i32 2
-; CHECK-NEXT: [[TMP5:%.*]] = extractelement <8 x double> [[TMP1]], i32 3
-; CHECK-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[TMP5]], i32 3
-; CHECK-NEXT: [[TMP6:%.*]] = extractelement <8 x double> [[TMP1]], i32 4
-; CHECK-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[TMP6]], i32 4
-; CHECK-NEXT: [[TMP7:%.*]] = extractelement <8 x double> [[TMP1]], i32 5
-; CHECK-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[TMP7]], i32 5
-; CHECK-NEXT: [[TMP8:%.*]] = extractelement <8 x double> [[TMP1]], i32 6
-; CHECK-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[TMP8]], i32 6
-; CHECK-NEXT: [[TMP9:%.*]] = extractelement <8 x double> [[TMP1]], i32 7
-; CHECK-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[TMP9]], i32 7
-; CHECK-NEXT: ret <8 x double> [[R7]]
+; SSE-LABEL: @buildvector_div_8f64(
+; SSE-NEXT: [[TMP1:%.*]] = fdiv <8 x double> [[A:%.*]], [[B:%.*]]
+; SSE-NEXT: [[TMP2:%.*]] = extractelement <8 x double> [[TMP1]], i32 0
+; SSE-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0
+; SSE-NEXT: [[TMP3:%.*]] = extractelement <8 x double> [[TMP1]], i32 1
+; SSE-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[TMP3]], i32 1
+; SSE-NEXT: [[TMP4:%.*]] = extractelement <8 x double> [[TMP1]], i32 2
+; SSE-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[TMP4]], i32 2
+; SSE-NEXT: [[TMP5:%.*]] = extractelement <8 x double> [[TMP1]], i32 3
+; SSE-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[TMP5]], i32 3
+; SSE-NEXT: [[TMP6:%.*]] = extractelement <8 x double> [[TMP1]], i32 4
+; SSE-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[TMP6]], i32 4
+; SSE-NEXT: [[TMP7:%.*]] = extractelement <8 x double> [[TMP1]], i32 5
+; SSE-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[TMP7]], i32 5
+; SSE-NEXT: [[TMP8:%.*]] = extractelement <8 x double> [[TMP1]], i32 6
+; SSE-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[TMP8]], i32 6
+; SSE-NEXT: [[TMP9:%.*]] = extractelement <8 x double> [[TMP1]], i32 7
+; SSE-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[TMP9]], i32 7
+; SSE-NEXT: ret <8 x double> [[R7]]
+;
+; SLM-LABEL: @buildvector_div_8f64(
+; SLM-NEXT: [[A0:%.*]] = extractelement <8 x double> [[A:%.*]], i32 0
+; SLM-NEXT: [[A1:%.*]] = extractelement <8 x double> [[A]], i32 1
+; SLM-NEXT: [[A2:%.*]] = extractelement <8 x double> [[A]], i32 2
+; SLM-NEXT: [[A3:%.*]] = extractelement <8 x double> [[A]], i32 3
+; SLM-NEXT: [[A4:%.*]] = extractelement <8 x double> [[A]], i32 4
+; SLM-NEXT: [[A5:%.*]] = extractelement <8 x double> [[A]], i32 5
+; SLM-NEXT: [[A6:%.*]] = extractelement <8 x double> [[A]], i32 6
+; SLM-NEXT: [[A7:%.*]] = extractelement <8 x double> [[A]], i32 7
+; SLM-NEXT: [[B0:%.*]] = extractelement <8 x double> [[B:%.*]], i32 0
+; SLM-NEXT: [[B1:%.*]] = extractelement <8 x double> [[B]], i32 1
+; SLM-NEXT: [[B2:%.*]] = extractelement <8 x double> [[B]], i32 2
+; SLM-NEXT: [[B3:%.*]] = extractelement <8 x double> [[B]], i32 3
+; SLM-NEXT: [[B4:%.*]] = extractelement <8 x double> [[B]], i32 4
+; SLM-NEXT: [[B5:%.*]] = extractelement <8 x double> [[B]], i32 5
+; SLM-NEXT: [[B6:%.*]] = extractelement <8 x double> [[B]], i32 6
+; SLM-NEXT: [[B7:%.*]] = extractelement <8 x double> [[B]], i32 7
+; SLM-NEXT: [[C0:%.*]] = fdiv double [[A0]], [[B0]]
+; SLM-NEXT: [[C1:%.*]] = fdiv double [[A1]], [[B1]]
+; SLM-NEXT: [[C2:%.*]] = fdiv double [[A2]], [[B2]]
+; SLM-NEXT: [[C3:%.*]] = fdiv double [[A3]], [[B3]]
+; SLM-NEXT: [[C4:%.*]] = fdiv double [[A4]], [[B4]]
+; SLM-NEXT: [[C5:%.*]] = fdiv double [[A5]], [[B5]]
+; SLM-NEXT: [[C6:%.*]] = fdiv double [[A6]], [[B6]]
+; SLM-NEXT: [[C7:%.*]] = fdiv double [[A7]], [[B7]]
+; SLM-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[C0]], i32 0
+; SLM-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[C1]], i32 1
+; SLM-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[C2]], i32 2
+; SLM-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[C3]], i32 3
+; SLM-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[C4]], i32 4
+; SLM-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[C5]], i32 5
+; SLM-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[C6]], i32 6
+; SLM-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[C7]], i32 7
+; SLM-NEXT: ret <8 x double> [[R7]]
+;
+; AVX-LABEL: @buildvector_div_8f64(
+; AVX-NEXT: [[TMP1:%.*]] = fdiv <8 x double> [[A:%.*]], [[B:%.*]]
+; AVX-NEXT: [[TMP2:%.*]] = extractelement <8 x double> [[TMP1]], i32 0
+; AVX-NEXT: [[R0:%.*]] = insertelement <8 x double> undef, double [[TMP2]], i32 0
+; AVX-NEXT: [[TMP3:%.*]] = extractelement <8 x double> [[TMP1]], i32 1
+; AVX-NEXT: [[R1:%.*]] = insertelement <8 x double> [[R0]], double [[TMP3]], i32 1
+; AVX-NEXT: [[TMP4:%.*]] = extractelement <8 x double> [[TMP1]], i32 2
+; AVX-NEXT: [[R2:%.*]] = insertelement <8 x double> [[R1]], double [[TMP4]], i32 2
+; AVX-NEXT: [[TMP5:%.*]] = extractelement <8 x double> [[TMP1]], i32 3
+; AVX-NEXT: [[R3:%.*]] = insertelement <8 x double> [[R2]], double [[TMP5]], i32 3
+; AVX-NEXT: [[TMP6:%.*]] = extractelement <8 x double> [[TMP1]], i32 4
+; AVX-NEXT: [[R4:%.*]] = insertelement <8 x double> [[R3]], double [[TMP6]], i32 4
+; AVX-NEXT: [[TMP7:%.*]] = extractelement <8 x double> [[TMP1]], i32 5
+; AVX-NEXT: [[R5:%.*]] = insertelement <8 x double> [[R4]], double [[TMP7]], i32 5
+; AVX-NEXT: [[TMP8:%.*]] = extractelement <8 x double> [[TMP1]], i32 6
+; AVX-NEXT: [[R6:%.*]] = insertelement <8 x double> [[R5]], double [[TMP8]], i32 6
+; AVX-NEXT: [[TMP9:%.*]] = extractelement <8 x double> [[TMP1]], i32 7
+; AVX-NEXT: [[R7:%.*]] = insertelement <8 x double> [[R6]], double [[TMP9]], i32 7
+; AVX-NEXT: ret <8 x double> [[R7]]
;
%a0 = extractelement <8 x double> %a, i32 0
%a1 = extractelement <8 x double> %a, i32 1
diff --git a/test/Transforms/SLPVectorizer/X86/arith-mul.ll b/test/Transforms/SLPVectorizer/X86/arith-mul.ll
index 95875d7f01fd..4763a9a2bf12 100644
--- a/test/Transforms/SLPVectorizer/X86/arith-mul.ll
+++ b/test/Transforms/SLPVectorizer/X86/arith-mul.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE
+; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX1
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX2
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512 --check-prefix=AVX512F
@@ -54,6 +55,41 @@ define void @mul_v8i64() {
; SSE-NEXT: store i64 [[R7]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 7), align 8
; SSE-NEXT: ret void
;
+; SLM-LABEL: @mul_v8i64(
+; SLM-NEXT: [[A0:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 0), align 8
+; SLM-NEXT: [[A1:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 1), align 8
+; SLM-NEXT: [[A2:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 2), align 8
+; SLM-NEXT: [[A3:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 3), align 8
+; SLM-NEXT: [[A4:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4), align 8
+; SLM-NEXT: [[A5:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 5), align 8
+; SLM-NEXT: [[A6:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 6), align 8
+; SLM-NEXT: [[A7:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 7), align 8
+; SLM-NEXT: [[B0:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 0), align 8
+; SLM-NEXT: [[B1:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 1), align 8
+; SLM-NEXT: [[B2:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 2), align 8
+; SLM-NEXT: [[B3:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 3), align 8
+; SLM-NEXT: [[B4:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 4), align 8
+; SLM-NEXT: [[B5:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 5), align 8
+; SLM-NEXT: [[B6:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 6), align 8
+; SLM-NEXT: [[B7:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 7), align 8
+; SLM-NEXT: [[R0:%.*]] = mul i64 [[A0]], [[B0]]
+; SLM-NEXT: [[R1:%.*]] = mul i64 [[A1]], [[B1]]
+; SLM-NEXT: [[R2:%.*]] = mul i64 [[A2]], [[B2]]
+; SLM-NEXT: [[R3:%.*]] = mul i64 [[A3]], [[B3]]
+; SLM-NEXT: [[R4:%.*]] = mul i64 [[A4]], [[B4]]
+; SLM-NEXT: [[R5:%.*]] = mul i64 [[A5]], [[B5]]
+; SLM-NEXT: [[R6:%.*]] = mul i64 [[A6]], [[B6]]
+; SLM-NEXT: [[R7:%.*]] = mul i64 [[A7]], [[B7]]
+; SLM-NEXT: store i64 [[R0]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 0), align 8
+; SLM-NEXT: store i64 [[R1]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 1), align 8
+; SLM-NEXT: store i64 [[R2]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 2), align 8
+; SLM-NEXT: store i64 [[R3]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 3), align 8
+; SLM-NEXT: store i64 [[R4]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 4), align 8
+; SLM-NEXT: store i64 [[R5]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 5), align 8
+; SLM-NEXT: store i64 [[R6]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6), align 8
+; SLM-NEXT: store i64 [[R7]], i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 7), align 8
+; SLM-NEXT: ret void
+;
; AVX1-LABEL: @mul_v8i64(
; AVX1-NEXT: [[A0:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 0), align 8
; AVX1-NEXT: [[A1:%.*]] = load i64, i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 1), align 8
@@ -162,6 +198,25 @@ define void @mul_v16i32() {
; SSE-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4
; SSE-NEXT: ret void
;
+; SLM-LABEL: @mul_v16i32(
+; SLM-NEXT: [[TMP1:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @a32 to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @b32 to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP9:%.*]] = mul <4 x i32> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = mul <4 x i32> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = mul <4 x i32> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = mul <4 x i32> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <4 x i32> [[TMP9]], <4 x i32>* bitcast ([16 x i32]* @c32 to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP10]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP11]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @mul_v16i32(
; AVX-NEXT: [[TMP1:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([16 x i32]* @a32 to <8 x i32>*), align 4
; AVX-NEXT: [[TMP2:%.*]] = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <8 x i32>*), align 4
@@ -267,6 +322,25 @@ define void @mul_v32i16() {
; SSE-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2
; SSE-NEXT: ret void
;
+; SLM-LABEL: @mul_v32i16(
+; SLM-NEXT: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @a16 to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @b16 to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP9:%.*]] = mul <8 x i16> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = mul <8 x i16> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = mul <8 x i16> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = mul <8 x i16> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <8 x i16> [[TMP9]], <8 x i16>* bitcast ([32 x i16]* @c16 to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP10]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP11]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @mul_v32i16(
; AVX-NEXT: [[TMP1:%.*]] = load <16 x i16>, <16 x i16>* bitcast ([32 x i16]* @a16 to <16 x i16>*), align 2
; AVX-NEXT: [[TMP2:%.*]] = load <16 x i16>, <16 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <16 x i16>*), align 2
diff --git a/test/Transforms/SLPVectorizer/X86/arith-sub.ll b/test/Transforms/SLPVectorizer/X86/arith-sub.ll
index 85838369e226..2bbaaca02d88 100644
--- a/test/Transforms/SLPVectorizer/X86/arith-sub.ll
+++ b/test/Transforms/SLPVectorizer/X86/arith-sub.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -mtriple=x86_64-unknown -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SSE
+; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=slm -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=SLM
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=corei7-avx -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX1
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=core-avx2 -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX --check-prefix=AVX2
; RUN: opt < %s -mtriple=x86_64-unknown -mcpu=knl -basicaa -slp-vectorizer -S | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512 --check-prefix=AVX512F
@@ -38,6 +39,25 @@ define void @sub_v8i64() {
; SSE-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8
; SSE-NEXT: ret void
;
+; SLM-LABEL: @sub_v8i64(
+; SLM-NEXT: [[TMP1:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @a64 to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP2:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 2) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP3:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP4:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 6) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP5:%.*]] = load <2 x i64>, <2 x i64>* bitcast ([8 x i64]* @b64 to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP6:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 2) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP7:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 4) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP8:%.*]] = load <2 x i64>, <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @b64, i32 0, i64 6) to <2 x i64>*), align 8
+; SLM-NEXT: [[TMP9:%.*]] = sub <2 x i64> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = sub <2 x i64> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = sub <2 x i64> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = sub <2 x i64> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <2 x i64> [[TMP9]], <2 x i64>* bitcast ([8 x i64]* @c64 to <2 x i64>*), align 8
+; SLM-NEXT: store <2 x i64> [[TMP10]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 2) to <2 x i64>*), align 8
+; SLM-NEXT: store <2 x i64> [[TMP11]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 4) to <2 x i64>*), align 8
+; SLM-NEXT: store <2 x i64> [[TMP12]], <2 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @c64, i32 0, i64 6) to <2 x i64>*), align 8
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @sub_v8i64(
; AVX-NEXT: [[TMP1:%.*]] = load <4 x i64>, <4 x i64>* bitcast ([8 x i64]* @a64 to <4 x i64>*), align 8
; AVX-NEXT: [[TMP2:%.*]] = load <4 x i64>, <4 x i64>* bitcast (i64* getelementptr inbounds ([8 x i64], [8 x i64]* @a64, i32 0, i64 4) to <4 x i64>*), align 8
@@ -111,6 +131,25 @@ define void @sub_v16i32() {
; SSE-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4
; SSE-NEXT: ret void
;
+; SLM-LABEL: @sub_v16i32(
+; SLM-NEXT: [[TMP1:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @a32 to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP2:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP3:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP4:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP5:%.*]] = load <4 x i32>, <4 x i32>* bitcast ([16 x i32]* @b32 to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP6:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP7:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP8:%.*]] = load <4 x i32>, <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @b32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: [[TMP9:%.*]] = sub <4 x i32> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = sub <4 x i32> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = sub <4 x i32> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = sub <4 x i32> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <4 x i32> [[TMP9]], <4 x i32>* bitcast ([16 x i32]* @c32 to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP10]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 4) to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP11]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 8) to <4 x i32>*), align 4
+; SLM-NEXT: store <4 x i32> [[TMP12]], <4 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @c32, i32 0, i64 12) to <4 x i32>*), align 4
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @sub_v16i32(
; AVX-NEXT: [[TMP1:%.*]] = load <8 x i32>, <8 x i32>* bitcast ([16 x i32]* @a32 to <8 x i32>*), align 4
; AVX-NEXT: [[TMP2:%.*]] = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([16 x i32], [16 x i32]* @a32, i32 0, i64 8) to <8 x i32>*), align 4
@@ -216,6 +255,25 @@ define void @sub_v32i16() {
; SSE-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2
; SSE-NEXT: ret void
;
+; SLM-LABEL: @sub_v32i16(
+; SLM-NEXT: [[TMP1:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @a16 to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP2:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP3:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP4:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP5:%.*]] = load <8 x i16>, <8 x i16>* bitcast ([32 x i16]* @b16 to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP6:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP7:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP8:%.*]] = load <8 x i16>, <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @b16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: [[TMP9:%.*]] = sub <8 x i16> [[TMP1]], [[TMP5]]
+; SLM-NEXT: [[TMP10:%.*]] = sub <8 x i16> [[TMP2]], [[TMP6]]
+; SLM-NEXT: [[TMP11:%.*]] = sub <8 x i16> [[TMP3]], [[TMP7]]
+; SLM-NEXT: [[TMP12:%.*]] = sub <8 x i16> [[TMP4]], [[TMP8]]
+; SLM-NEXT: store <8 x i16> [[TMP9]], <8 x i16>* bitcast ([32 x i16]* @c16 to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP10]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 8) to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP11]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 16) to <8 x i16>*), align 2
+; SLM-NEXT: store <8 x i16> [[TMP12]], <8 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @c16, i32 0, i64 24) to <8 x i16>*), align 2
+; SLM-NEXT: ret void
+;
; AVX-LABEL: @sub_v32i16(
; AVX-NEXT: [[TMP1:%.*]] = load <16 x i16>, <16 x i16>* bitcast ([32 x i16]* @a16 to <16 x i16>*), align 2
; AVX-NEXT: [[TMP2:%.*]] = load <16 x i16>, <16 x i16>* bitcast (i16* getelementptr inbounds ([32 x i16], [32 x i16]* @a16, i32 0, i64 16) to <16 x i16>*), align 2
diff --git a/test/Transforms/SafeStack/X86/debug-loc.ll b/test/Transforms/SafeStack/X86/debug-loc.ll
index 88cda693b293..d6b217142bfe 100644
--- a/test/Transforms/SafeStack/X86/debug-loc.ll
+++ b/test/Transforms/SafeStack/X86/debug-loc.ll
@@ -37,10 +37,10 @@ entry:
; CHECK-DAG: ![[VAR_ARG]] = !DILocalVariable(name: "zzz"
; 100 aligned up to 8
-; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_minus, 104)
+; CHECK-DAG: ![[EXPR_ARG]] = !DIExpression(DW_OP_constu, 104, DW_OP_minus
; CHECK-DAG: ![[VAR_LOCAL]] = !DILocalVariable(name: "xxx"
-; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_minus, 208)
+; CHECK-DAG: ![[EXPR_LOCAL]] = !DIExpression(DW_OP_constu, 208, DW_OP_minus
; Function Attrs: nounwind readnone
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
diff --git a/test/Transforms/SafeStack/X86/debug-loc2.ll b/test/Transforms/SafeStack/X86/debug-loc2.ll
index 8059a722fd45..731516c3c65e 100644
--- a/test/Transforms/SafeStack/X86/debug-loc2.ll
+++ b/test/Transforms/SafeStack/X86/debug-loc2.ll
@@ -84,8 +84,8 @@ attributes #4 = { nounwind }
!13 = !DILocation(line: 5, column: 3, scope: !6)
!14 = !DILocation(line: 6, column: 3, scope: !6)
-; CHECK-DAG: ![[X1_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_minus, 4)
-; CHECK-DAG: ![[X2_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_minus, 8)
+; CHECK-DAG: ![[X1_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_constu, 4, DW_OP_minus)
+; CHECK-DAG: ![[X2_EXPR]] = !DIExpression(DW_OP_deref, DW_OP_constu, 8, DW_OP_minus)
!15 = !DIExpression(DW_OP_deref)
!16 = !DILocation(line: 5, column: 7, scope: !6)
!17 = !DILocation(line: 8, column: 3, scope: !6)
@@ -95,4 +95,4 @@ attributes #4 = { nounwind }
!21 = !DILocation(line: 10, column: 1, scope: !22)
!22 = !DILexicalBlockFile(scope: !6, file: !1, discriminator: 1)
!23 = !DIExpression()
-!24 = !DIExpression(DW_OP_minus, 42)
+!24 = !DIExpression(DW_OP_constu, 42, DW_OP_minus)
diff --git a/test/Transforms/Util/PredicateInfo/pr33456.ll b/test/Transforms/Util/PredicateInfo/pr33456.ll
new file mode 100644
index 000000000000..f1cc83a071b9
--- /dev/null
+++ b/test/Transforms/Util/PredicateInfo/pr33456.ll
@@ -0,0 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
+; Don't insert predicate info for conditions with a single target.
+@a = global i32 1, align 4
+@d = common global i32 0, align 4
+@c = common global i32 0, align 4
+@b = common global i32 0, align 4
+@e = common global i32 0, align 4
+
+define i32 @main() {
+; CHECK-LABEL: @main(
+; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @d, align 4
+; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0
+; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP13:%.*]]
+; CHECK: [[TMP4:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* @c, align 4
+; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP5]], 1
+; CHECK-NEXT: br i1 [[TMP6]], label [[TMP7:%.*]], label [[TMP9:%.*]]
+; CHECK: [[TMP8:%.*]] = icmp eq i32 [[TMP4]], 0
+; CHECK-NEXT: br i1 [[TMP8]], label [[TMP9]], label [[TMP9]]
+; CHECK: [[DOT0:%.*]] = phi i32 [ [[TMP4]], [[TMP7]] ], [ [[TMP4]], [[TMP7]] ], [ [[DOT1:%.*]], [[TMP13]] ], [ [[TMP4]], [[TMP3]] ]
+; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* @b, align 4
+; CHECK-NEXT: [[TMP11:%.*]] = sdiv i32 [[TMP10]], [[DOT0]]
+; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i32 [[TMP11]], 0
+; CHECK-NEXT: br i1 [[TMP12]], label [[TMP13]], label [[TMP13]]
+; CHECK: [[DOT1]] = phi i32 [ [[DOT0]], [[TMP9]] ], [ [[DOT0]], [[TMP9]] ], [ undef, [[TMP0:%.*]] ]
+; CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* @e, align 4
+; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i32 [[TMP14]], 0
+; CHECK-NEXT: br i1 [[TMP15]], label [[TMP16:%.*]], label [[TMP9]]
+; CHECK: ret i32 0
+;
+ %1 = load i32, i32* @d, align 4
+ %2 = icmp eq i32 %1, 0
+ br i1 %2, label %3, label %13
+
+; <label>:3: ; preds = %0
+ %4 = load i32, i32* @a, align 4
+ %5 = load i32, i32* @c, align 4
+ %6 = icmp slt i32 %5, 1
+ br i1 %6, label %7, label %9
+
+; <label>:7: ; preds = %3
+ %8 = icmp eq i32 %4, 0
+ br i1 %8, label %9, label %9
+
+; <label>:9: ; preds = %13, %7, %7, %3
+ %.0 = phi i32 [ %4, %7 ], [ %4, %7 ], [ %.1, %13 ], [ %4, %3 ]
+ %10 = load i32, i32* @b, align 4
+ %11 = sdiv i32 %10, %.0
+ %12 = icmp eq i32 %11, 0
+ br i1 %12, label %13, label %13
+
+; <label>:13: ; preds = %9, %9, %0
+ %.1 = phi i32 [ %.0, %9 ], [ %.0, %9 ], [ undef, %0 ]
+ %14 = load i32, i32* @e, align 4
+ %15 = icmp eq i32 %14, 0
+ br i1 %15, label %16, label %9
+
+; <label>:16: ; preds = %13
+ ret i32 0
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
+
diff --git a/test/Transforms/Util/PredicateInfo/pr33457.ll b/test/Transforms/Util/PredicateInfo/pr33457.ll
new file mode 100644
index 000000000000..b975ade9321d
--- /dev/null
+++ b/test/Transforms/Util/PredicateInfo/pr33457.ll
@@ -0,0 +1,93 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -print-predicateinfo -analyze < %s 2>&1 | FileCheck %s
+; Don't insert predicate info for conditions with a single target.
+@a = global i32 6, align 4
+@c = global i32 -1, align 4
+@e = common global i32 0, align 4
+@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
+@d = common global i32 0, align 4
+@b = common global [6 x i32] zeroinitializer, align 16
+
+; Function Attrs: nounwind ssp uwtable
+define i32 @main() {
+; CHECK-LABEL: @main(
+; CHECK-NEXT: store i32 6, i32* @e, align 4
+; CHECK-NEXT: br label [[TMP1:%.*]]
+; CHECK: [[TMP2:%.*]] = load i32, i32* @d, align 4
+; CHECK-NEXT: [[TMP3:%.*]] = sext i32 [[TMP2]] to i64
+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [6 x i32], [6 x i32]* @b, i64 0, i64 [[TMP3]]
+; CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* [[TMP4]], align 4
+; CHECK-NEXT: [[TMP6:%.*]] = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 [[TMP5]])
+; CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* @a, align 4
+; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i32 [[TMP7]], 0
+; CHECK-NEXT: br i1 [[TMP8]], label %thread-pre-split, label [[TMP9:%.*]]
+; CHECK: [[TMP10:%.*]] = load i32, i32* @e, align 4
+; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[TMP10]], 0
+; CHECK-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP12]]
+; CHECK: thread-pre-split:
+; CHECK-NEXT: [[DOTPR:%.*]] = load i32, i32* @e, align 4
+; CHECK-NEXT: br label [[TMP12]]
+; CHECK: [[TMP13:%.*]] = phi i32 [ [[DOTPR]], %thread-pre-split ], [ [[TMP10]], [[TMP9]] ], [ [[TMP10]], [[TMP9]] ]
+; CHECK-NEXT: [[TMP14:%.*]] = icmp ne i32 [[TMP13]], 0
+; CHECK-NEXT: br i1 [[TMP14]], label [[TMP15:%.*]], label [[TMP15]]
+; CHECK: br i1 [[TMP14]], label [[TMP16:%.*]], label [[TMP17:%.*]]
+; CHECK: br label [[TMP17]]
+; CHECK: [[DOT0:%.*]] = phi i32 [ 1, [[TMP16]] ], [ -1, [[TMP15]] ]
+; CHECK-NEXT: [[TMP18:%.*]] = and i32 [[DOT0]], 8693
+; CHECK-NEXT: [[TMP19:%.*]] = load i32, i32* @c, align 4
+; CHECK-NEXT: [[TMP20:%.*]] = xor i32 [[TMP18]], [[TMP19]]
+; CHECK-NEXT: [[TMP21:%.*]] = xor i32 [[TMP20]], -1
+; CHECK-NEXT: store i32 [[TMP21]], i32* @d, align 4
+; CHECK-NEXT: [[TMP22:%.*]] = icmp slt i32 [[TMP20]], -2
+; CHECK-NEXT: br i1 [[TMP22]], label [[TMP1]], label [[TMP23:%.*]]
+; CHECK: ret i32 0
+;
+ store i32 6, i32* @e, align 4
+ br label %1
+
+; <label>:1: ; preds = %17, %0
+ %2 = load i32, i32* @d, align 4
+ %3 = sext i32 %2 to i64
+ %4 = getelementptr inbounds [6 x i32], [6 x i32]* @b, i64 0, i64 %3
+ %5 = load i32, i32* %4, align 4
+ %6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 %5) #2
+ %7 = load i32, i32* @a, align 4
+ %8 = icmp eq i32 %7, 0
+ br i1 %8, label %thread-pre-split, label %9
+
+; <label>:9: ; preds = %1
+ %10 = load i32, i32* @e, align 4
+ %11 = icmp eq i32 %10, 0
+ br i1 %11, label %12, label %12
+
+thread-pre-split: ; preds = %1
+ %.pr = load i32, i32* @e, align 4
+ br label %12
+
+; <label>:12: ; preds = %thread-pre-split, %9, %9
+ %13 = phi i32 [ %.pr, %thread-pre-split ], [ %10, %9 ], [ %10, %9 ]
+ %14 = icmp ne i32 %13, 0
+ br i1 %14, label %15, label %15
+
+; <label>:15: ; preds = %12, %12
+ br i1 %14, label %16, label %17
+
+; <label>:16: ; preds = %15
+ br label %17
+
+; <label>:17: ; preds = %16, %15
+ %.0 = phi i32 [ 1, %16 ], [ -1, %15 ]
+ %18 = and i32 %.0, 8693
+ %19 = load i32, i32* @c, align 4
+ %20 = xor i32 %18, %19
+ %21 = xor i32 %20, -1
+ store i32 %21, i32* @d, align 4
+ %22 = icmp slt i32 %20, -2
+ br i1 %22, label %1, label %23
+
+; <label>:23: ; preds = %17
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
+
diff --git a/test/Verifier/element-wise-atomic-memory-intrinsics.ll b/test/Verifier/element-wise-atomic-memory-intrinsics.ll
index 5690cd721407..470c861c5057 100644
--- a/test/Verifier/element-wise-atomic-memory-intrinsics.ll
+++ b/test/Verifier/element-wise-atomic-memory-intrinsics.ll
@@ -1,17 +1,25 @@
; RUN: not opt -verify < %s 2>&1 | FileCheck %s
-define void @test_memcpy(i8* %P, i8* %Q) {
+define void @test_memcpy(i8* %P, i8* %Q, i32 %A, i32 %E) {
+ ; CHECK: element size of the element-wise unordered atomic memory intrinsic must be a constant int
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 1, i32 %E)
; CHECK: element size of the element-wise atomic memory intrinsic must be a power of 2
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 2 %P, i8* align 2 %Q, i64 4, i32 3)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 1, i32 3)
+ ; CHECK: constant length must be a multiple of the element size in the element-wise atomic memory intrinsic
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 4 %Q, i32 7, i32 4)
+
+ ; CHECK: incorrect alignment of the destination argument
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* %P, i8* align 4 %Q, i32 1, i32 1)
; CHECK: incorrect alignment of the destination argument
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 2 %P, i8* align 4 %Q, i64 4, i32 4)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 1 %P, i8* align 4 %Q, i32 4, i32 4)
; CHECK: incorrect alignment of the source argument
- call void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* align 4 %P, i8* align 2 %Q, i64 4, i32 4)
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* %Q, i32 1, i32 1)
+ ; CHECK: incorrect alignment of the source argument
+ call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* align 4 %P, i8* align 1 %Q, i32 4, i32 4)
ret void
}
-declare void @llvm.memcpy.element.atomic.p0i8.p0i8(i8* nocapture, i8* nocapture, i64, i32) nounwind
-
+declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind
; CHECK: input module is broken!
diff --git a/test/lit.cfg b/test/lit.cfg
index 5e903c26657e..ed1ba2d11b1a 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -301,7 +301,7 @@ for pattern in [r"\bbugpoint\b(?!-)",
r"\bllvm-modextract\b",
r"\bllvm-nm\b",
r"\bllvm-objdump\b",
- r"\bllvm-pdbdump\b",
+ r"\bllvm-pdbutil\b",
r"\bllvm-profdata\b",
r"\bllvm-ranlib\b",
r"\bllvm-readobj\b",
diff --git a/test/tools/llvm-cvtres/Inputs/combined.obj.coff b/test/tools/llvm-cvtres/Inputs/combined.obj.coff
new file mode 100644
index 000000000000..bbb670b258e7
--- /dev/null
+++ b/test/tools/llvm-cvtres/Inputs/combined.obj.coff
Binary files differ
diff --git a/test/tools/llvm-cvtres/Inputs/languages.rc b/test/tools/llvm-cvtres/Inputs/languages.rc
new file mode 100644
index 000000000000..081b3a77bebc
--- /dev/null
+++ b/test/tools/llvm-cvtres/Inputs/languages.rc
@@ -0,0 +1,36 @@
+#include "windows.h"
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+randomdat RCDATA
+{
+ "this is a random bit of data that means nothing\0",
+ 0x23a9,
+ 0x140e,
+ 194292,
+}
+
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+randomdat RCDATA
+{
+ "zhe4 shi4 yi1ge4 sui2ji1 de shu4ju4, zhe4 yi4wei4zhe shen2me\0",
+ 0x23a9,
+ 0x140e,
+ 194292,
+}
+
+LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG
+randomdat RCDATA
+{
+ "Dies ist ein zufälliges Bit von Daten, die nichts bedeutet\0",
+ 0x23a9,
+ 0x140e,
+ 194292,
+}
+
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+myaccelerators ACCELERATORS
+{
+ "^C", 999, VIRTKEY, ALT
+ "D", 1100, VIRTKEY, CONTROL, SHIFT
+ "^R", 444, ASCII, NOINVERT
+}
diff --git a/test/tools/llvm-cvtres/Inputs/languages.res b/test/tools/llvm-cvtres/Inputs/languages.res
new file mode 100644
index 000000000000..31da6166d7f6
--- /dev/null
+++ b/test/tools/llvm-cvtres/Inputs/languages.res
Binary files differ
diff --git a/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.arm b/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.arm
new file mode 100644
index 000000000000..ca2f9a4fd04e
--- /dev/null
+++ b/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.arm
Binary files differ
diff --git a/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.x64 b/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.x64
new file mode 100644
index 000000000000..4620f97f0af1
--- /dev/null
+++ b/test/tools/llvm-cvtres/Inputs/test_resource.obj.coff.x64
Binary files differ
diff --git a/test/tools/llvm-cvtres/basic.test b/test/tools/llvm-cvtres/basic.test
deleted file mode 100644
index fcebef22f650..000000000000
--- a/test/tools/llvm-cvtres/basic.test
+++ /dev/null
@@ -1,4 +0,0 @@
-; RUN: llvm-cvtres /h > %t
-; RUN: FileCheck -input-file=%t %s -check-prefix=HELP_TEST
-
-; HELP_TEST: OVERVIEW: Resource Converter
diff --git a/test/tools/llvm-cvtres/combined.test b/test/tools/llvm-cvtres/combined.test
new file mode 100644
index 000000000000..084a0ea0cdec
--- /dev/null
+++ b/test/tools/llvm-cvtres/combined.test
@@ -0,0 +1,313 @@
+// Check that cvtres properly handles merging multiple .res files.
+// The inputs were generated with the following commands, using the original Windows
+// rc.exe:
+// > rc /fo test_resource.res /nologo test_resource.rc
+// > rc /fo languages.res /nologo languages.rc
+// The object file we are comparing against was generated with this command using
+// the original Windows cvtres.exe.
+// > cvtres /machine:X86 /readonly /nologo /out:combined.obj.coff \
+// languages.res test_resource.res
+
+RUN: llvm-cvtres /verbose /out:%t %p/Inputs/languages.res %p/Inputs/test_resource.res
+RUN: llvm-readobj -coff-resources -section-data %t | FileCheck %s
+
+CHECK: Resources [
+CHECK-NEXT: Total Number of Resources: 12
+CHECK-DAG: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 5
+CHECK-NEXT: Type: STRINGARRAY [
+CHECK-NEXT: Table Offset: 0x40
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 0
+CHECK-NEXT: Name: MYRESOURCE [
+CHECK-NEXT: Table Offset: 0xE8
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x1D8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_BITMAP (ID 2) [
+CHECK-NEXT: Table Offset: 0x58
+CHECK-NEXT: Number of String Entries: 2
+CHECK-NEXT: Number of ID Entries: 0
+CHECK-NEXT: Name: CURSOR [
+CHECK-NEXT: Table Offset: 0x100
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x1E8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Name: OKAY [
+CHECK-NEXT: Table Offset: 0x118
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x1F8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_MENU (ID 4) [
+CHECK-NEXT: Table Offset: 0x78
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Name: "EAT" [
+CHECK-NEXT: Table Offset: 0x130
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 3081) [
+CHECK-NEXT: Entry Offset: 0x208
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Name: (ID 14432) [
+CHECK-NEXT: Table Offset: 0x148
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 2052) [
+CHECK-NEXT: Entry Offset: 0x218
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_DIALOG (ID 5) [
+CHECK-NEXT: Table Offset: 0x98
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 0
+CHECK-NEXT: Name: TESTDIALOG [
+CHECK-NEXT: Table Offset: 0x160
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x228
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_ACCELERATOR (ID 9) [
+CHECK-NEXT: Table Offset: 0xB0
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Name: MYACCELERATORS [
+CHECK-NEXT: Table Offset: 0x178
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 2
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x238
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: Language: (ID 2052) [
+CHECK-NEXT: Entry Offset: 0x248
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Name: (ID 12) [
+CHECK-NEXT: Table Offset: 0x198
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x258
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_RCDATA (ID 10) [
+CHECK-NEXT: Table Offset: 0xD0
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 0
+CHECK-NEXT: Name: RANDOMDAT [
+CHECK-NEXT: Table Offset: 0x1B0
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 3
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x268
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: Language: (ID 2052) [
+CHECK-NEXT: Entry Offset: 0x278
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: Language: (ID 4103) [
+CHECK-NEXT: Entry Offset: 0x288
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-DAG: .rsrc$02 Data (
+CHECK-NEXT: 0000: 74686973 20697320 61207261 6E646F6D |this is a random|
+CHECK-NEXT: 0010: 20626974 206F6620 64617461 20746861 | bit of data tha|
+CHECK-NEXT: 0020: 74206D65 616E7320 6E6F7468 696E6700 |t means nothing.|
+CHECK-NEXT: 0030: A9230E14 F4F60000 7A686534 20736869 |.#......zhe4 shi|
+CHECK-NEXT: 0040: 34207969 31676534 20737569 326A6931 |4 yi1ge4 sui2ji1|
+CHECK-NEXT: 0050: 20646520 73687534 6A75342C 207A6865 | de shu4ju4, zhe|
+CHECK-NEXT: 0060: 34207969 34776569 347A6865 20736865 |4 yi4wei4zhe she|
+CHECK-NEXT: 0070: 6E326D65 00A9230E 14F4F600 00000000 |n2me..#.........|
+CHECK-NEXT: 0080: 44696573 20697374 2065696E 207A7566 |Dies ist ein zuf|
+CHECK-NEXT: 0090: C3A46C6C 69676573 20426974 20766F6E |..lliges Bit von|
+CHECK-NEXT: 00A0: 20446174 656E2C20 64696520 6E696368 | Daten, die nich|
+CHECK-NEXT: 00B0: 74732062 65646575 74657400 A9230E14 |ts bedeutet..#..|
+CHECK-NEXT: 00C0: F4F60000 00000000 11000300 E7030000 |................|
+CHECK-NEXT: 00D0: 0D004400 4C040000 82001200 BC010000 |..D.L...........|
+CHECK-NEXT: 00E0: 11000300 E7030000 0D004400 4C040000 |..........D.L...|
+CHECK-NEXT: 00F0: 82001200 BC010000 28000000 10000000 |........(.......|
+CHECK-NEXT: 0100: 10000000 01001800 00000000 00030000 |................|
+CHECK-NEXT: 0110: C40E0000 C40E0000 00000000 00000000 |................|
+CHECK-NEXT: 0120: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0130: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0140: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0150: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0160: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0170: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0180: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0190: FFFFFFFF FF7F7F7F 7C7C7C78 78787575 |........|||xxxuu|
+CHECK-NEXT: 01A0: 75FFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |u...............|
+CHECK-NEXT: 01B0: FFFFFFFF FFFFFFFF FFFFFFFF 979797FF |................|
+CHECK-NEXT: 01C0: FFFFFFFF FF838383 AAAAAADB DBDB7979 |..............yy|
+CHECK-NEXT: 01D0: 79757575 FFFFFFFF FFFFFFFF FFFFFFFF |yuuu............|
+CHECK-NEXT: 01E0: FFFFFFFF FFFFFFFF FFFFFFFF 9C9C9C98 |................|
+CHECK-NEXT: 01F0: 9898FFFF FF888888 DBDBDBB7 B7B77D7D |..............}}|
+CHECK-NEXT: 0200: 7DFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |}...............|
+CHECK-NEXT: 0210: FFFFFFFF FFFFFFFF FFFFFFFF A0A0A09C |................|
+CHECK-NEXT: 0220: 9C9C9393 93ADADAD F2F2F284 84848181 |................|
+CHECK-NEXT: 0230: 81FFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0240: FFFFFFFF FFFFFFFF FFFFFFFF A4A4A4D7 |................|
+CHECK-NEXT: 0250: D7D79D9D 9DD0D0D0 EEEEEE91 91918D8D |................|
+CHECK-NEXT: 0260: 8DFFFFFF FFFFFF81 81817E7E 7EFFFFFF |..........~~~...|
+CHECK-NEXT: 0270: FFFFFFFF FFFFFFFF FFFFFFFF A9A9A9F2 |................|
+CHECK-NEXT: 0280: F2F2E5E5 E5E2E2E2 95959591 91918D8D |................|
+CHECK-NEXT: 0290: 8D898989 868686FF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 02A0: FFFFFFFF FFFFFFFF FFFFFFFF ADADADF2 |................|
+CHECK-NEXT: 02B0: F2F2E1E1 E1DFDFDF E7E7E7E4 E4E4BBBB |................|
+CHECK-NEXT: 02C0: BB8E8E8E FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 02D0: FFFFFFFF FFFFFFFF FFFFFFFF B5B5B5F2 |................|
+CHECK-NEXT: 02E0: F2F2E8E8 E8E7E7E7 EAEAEAC6 C6C69E9E |................|
+CHECK-NEXT: 02F0: 9EFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0300: FFFFFFFF FFFFFFFF FFFFFFFF B9B9B9F4 |................|
+CHECK-NEXT: 0310: F4F4ECEC ECEDEDED CBCBCBA7 A7A7FFFF |................|
+CHECK-NEXT: 0320: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0330: FFFFFFFF FFFFFFFF FFFFFFFF BDBDBDF7 |................|
+CHECK-NEXT: 0340: F7F7EFEF EFD0D0D0 AFAFAFFF FFFFFFFF |................|
+CHECK-NEXT: 0350: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0360: FFFFFFFF FFFFFFFF FFFFFFFF C1C1C1F7 |................|
+CHECK-NEXT: 0370: F7F7D5D5 D5B6B6B6 FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0380: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0390: FFFFFFFF FFFFFFFF FFFFFFFF C4C4C4D9 |................|
+CHECK-NEXT: 03A0: D9D9BEBE BEFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 03B0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 03C0: FFFFFFFF FFFFFFFF FFFFFFFF C8C8C8C5 |................|
+CHECK-NEXT: 03D0: C5C5FFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 03E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 03F0: FFFFFFFF FFFFFFFF FFFFFFFF CBCBCBFF |................|
+CHECK-NEXT: 0400: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0410: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0420: 28000000 10000000 10000000 01001800 |(...............|
+CHECK-NEXT: 0430: 00000000 00030000 C40E0000 C40E0000 |................|
+CHECK-NEXT: 0440: 00000000 00000000 FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0450: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0460: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0470: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0480: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0490: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 04A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 04B0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 04C0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 04D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 04E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 04F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0500: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0510: FFFFFFFF A0E3A901 B31801B3 1801B318 |................|
+CHECK-NEXT: 0520: 01B31801 B31801B3 1861D06F FFFFFFFF |.........a.o....|
+CHECK-NEXT: 0530: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0540: FFFFFFFF 01B31800 D7331CDB 49DBF9E2 |.........3..I...|
+CHECK-NEXT: 0550: 9BEFAF00 D73300D7 3301B318 FFFFFFFF |.....3..3.......|
+CHECK-NEXT: 0560: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0570: FFFFFFFF 01B31800 DE55F6FE F9DBFAE7 |.........U......|
+CHECK-NEXT: 0580: FEFFFE86 EFAE00DE 5501B318 FFFFFFFF |........U.......|
+CHECK-NEXT: 0590: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 05A0: FFFFFFFF 01B31800 E676DBFB EC00E676 |.........v.....v|
+CHECK-NEXT: 05B0: 57EFA5FB FFFD55EE A401B318 FFFFFFFF |W.....U.........|
+CHECK-NEXT: 05C0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 05D0: FFFFFFFF 01B31800 ED9800ED 9800ED98 |................|
+CHECK-NEXT: 05E0: 00ED9887 F7CFFEFF FF01B318 FFFFFFFF |................|
+CHECK-NEXT: 05F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0600: FFFFFFFF 01B31800 F4BA00F4 BA00F4BA |................|
+CHECK-NEXT: 0610: 00F4BA00 F4BA9CFB E401B318 FFFFFFFF |................|
+CHECK-NEXT: 0620: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0630: FFFFFFFF 01B31800 FBDB00FB DB00FBDB |................|
+CHECK-NEXT: 0640: 00FBDB00 FBDB00FB DB01B318 FFFFFFFF |................|
+CHECK-NEXT: 0650: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0660: FFFFFFFF 9FE2A801 B31801B3 1801B318 |................|
+CHECK-NEXT: 0670: 01B31801 B31801B3 1861D06F FFFFFFFF |.........a.o....|
+CHECK-NEXT: 0680: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0690: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 06A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 06B0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 06C0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 06D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 06E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 06F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0700: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0710: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0720: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0730: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF |................|
+CHECK-NEXT: 0740: FFFFFFFF FFFFFFFF 00000000 00006400 |..............d.|
+CHECK-NEXT: 0750: 79007500 00000000 65007300 68006100 |y.u.....e.s.h.a.|
+CHECK-NEXT: 0760: 6C006100 00008000 66006B00 61006F00 |l.a.....f.k.a.o.|
+CHECK-NEXT: 0770: 79006100 00000000 0000C080 00000000 |y.a.............|
+CHECK-NEXT: 0780: 02000A00 0A00C800 2C010000 00005400 |........,.....T.|
+CHECK-NEXT: 0790: 65007300 74000000 01000250 00000000 |e.s.t......P....|
+CHECK-NEXT: 07A0: 0A000A00 E6000E00 0100FFFF 82004300 |..............C.|
+CHECK-NEXT: 07B0: 6F006E00 74006900 6E007500 65003A00 |o.n.t.i.n.u.e.:.|
+CHECK-NEXT: 07C0: 00000000 00000150 00000000 42008600 |.......P....B...|
+CHECK-NEXT: 07D0: A1000D00 0200FFFF 80002600 4F004B00 |..........&.O.K.|
+CHECK-NEXT: 07E0: 00000000 00000000 11005800 A4000000 |..........X.....|
+CHECK-NEXT: 07F0: 0D004800 2E160000 82001200 BC010000 |..H.............|
+CHECK-NEXT: 0800: 00000000 00006400 66006900 73006800 |......d.f.i.s.h.|
+CHECK-NEXT: 0810: 00000000 65007300 61006C00 61006400 |....e.s.a.l.a.d.|
+CHECK-NEXT: 0820: 00008000 66006400 75006300 6B000000 |....f.d.u.c.k...|
+CHECK-NEXT: 0830: 74686973 20697320 61207573 65722064 |this is a user d|
+CHECK-NEXT: 0840: 6566696E 65642072 65736F75 72636500 |efined resource.|
+CHECK-NEXT: 0850: 69742063 6F6E7461 696E7320 6D616E79 |it contains many|
+CHECK-NEXT: 0860: 20737472 696E6773 00000000 00000000 | strings........|
+CHECK-NEXT: )
diff --git a/test/tools/llvm-cvtres/help.test b/test/tools/llvm-cvtres/help.test
new file mode 100644
index 000000000000..ed76e1f126e3
--- /dev/null
+++ b/test/tools/llvm-cvtres/help.test
@@ -0,0 +1,13 @@
+; RUN: llvm-cvtres /h > %t
+; RUN: FileCheck -input-file=%t %s -check-prefix=HELP_TEST
+
+; HELP_TEST: OVERVIEW: Resource Converter
+; HELP_TEST-DAG: USAGE: cvtres [options] <inputs>
+; HELP_TEST-DAG: OPTIONS:
+; HELP_TEST-NEXT: /DEFINE:symbol
+; HELP_TEST-NEXT: /FOLDDUPS:
+; HELP_TEST-NEXT: /MACHINE:{ARM|EBC|IA64|X64|X86}
+; HELP_TEST-DAG: /NOLOGO
+; HELP_TEST-NEXT: /OUT:filename
+; HELP_TEST-NEXT: /READONLY
+; HELP_TEST-NEXT: /VERBOSE
diff --git a/test/tools/llvm-cvtres/machine.test b/test/tools/llvm-cvtres/machine.test
new file mode 100644
index 000000000000..58096d1d8ed1
--- /dev/null
+++ b/test/tools/llvm-cvtres/machine.test
@@ -0,0 +1,59 @@
+// Check that cvtres properly generates COFF for different machine types. The
+// only things that changes with machine type are the machine constant listed
+// in the COFF header, and the relocation types in the relocation tables.
+// The input was generated with the following command, using the original Windows
+// rc.exe:
+// > rc /fo test_resource.res /nologo test_resource.rc
+// The object files we are comparing against were generated with these commands
+// using the original Windows cvtres.exe.
+// > cvtres /machine:X86 /readonly /nologo /out:test_resource.obj.coff \
+// test_resource.res
+// > cvtres /machine:X64 /readonly /nologo /out:test_resource.obj.coff.x64 \
+// test_resource.res
+// > cvtres /machine:ARM /readonly /nologo /out:test_resource.obj.coff.x64 \
+// test_resource.res
+
+RUN: llvm-cvtres /machine:X86 /out:%t %p/Inputs/test_resource.res
+RUN: llvm-readobj -h -relocations %t | FileCheck %s -check-prefix=X86
+
+RUN: llvm-cvtres /machine:X64 /out:%t %p/Inputs/test_resource.res
+RUN: llvm-readobj -h -relocations %t | FileCheck %s -check-prefix=X64
+
+RUN: llvm-cvtres /machine:ARM /out:%t %p/Inputs/test_resource.res
+RUN: llvm-readobj -h -relocations %t | FileCheck %s -check-prefix=ARM
+
+X86: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
+X86-DAG: Relocations [
+X86-DAG: .rsrc$01 {
+X86-NEXT: 0x1E8 IMAGE_REL_I386_DIR32NB $R000000
+X86-NEXT: 0x198 IMAGE_REL_I386_DIR32NB $R000018
+X86-NEXT: 0x1A8 IMAGE_REL_I386_DIR32NB $R000340
+X86-NEXT: 0x1C8 IMAGE_REL_I386_DIR32NB $R000668
+X86-NEXT: 0x1D8 IMAGE_REL_I386_DIR32NB $R000698
+X86-NEXT: 0x1F8 IMAGE_REL_I386_DIR32NB $R000708
+X86-NEXT: 0x1B8 IMAGE_REL_I386_DIR32NB $R000720
+X86-NEXT: 0x188 IMAGE_REL_I386_DIR32NB $R000750
+
+X64: Machine: IMAGE_FILE_MACHINE_AMD64 (0x8664)
+X64-DAG: Relocations [
+X64-DAG: .rsrc$01 {
+X64-NEXT: 0x1E8 IMAGE_REL_AMD64_ADDR32NB $R000000
+X64-NEXT: 0x198 IMAGE_REL_AMD64_ADDR32NB $R000018
+X64-NEXT: 0x1A8 IMAGE_REL_AMD64_ADDR32NB $R000340
+X64-NEXT: 0x1C8 IMAGE_REL_AMD64_ADDR32NB $R000668
+X64-NEXT: 0x1D8 IMAGE_REL_AMD64_ADDR32NB $R000698
+X64-NEXT: 0x1F8 IMAGE_REL_AMD64_ADDR32NB $R000708
+X64-NEXT: 0x1B8 IMAGE_REL_AMD64_ADDR32NB $R000720
+X64-NEXT: 0x188 IMAGE_REL_AMD64_ADDR32NB $R000750
+
+ARM: Machine: IMAGE_FILE_MACHINE_ARMNT (0x1C4)
+ARM-DAG: Relocations [
+ARM-DAG: .rsrc$01 {
+ARM-NEXT: 0x1E8 IMAGE_REL_ARM_ADDR32NB $R000000
+ARM-NEXT: 0x198 IMAGE_REL_ARM_ADDR32NB $R000018
+ARM-NEXT: 0x1A8 IMAGE_REL_ARM_ADDR32NB $R000340
+ARM-NEXT: 0x1C8 IMAGE_REL_ARM_ADDR32NB $R000668
+ARM-NEXT: 0x1D8 IMAGE_REL_ARM_ADDR32NB $R000698
+ARM-NEXT: 0x1F8 IMAGE_REL_ARM_ADDR32NB $R000708
+ARM-NEXT: 0x1B8 IMAGE_REL_ARM_ADDR32NB $R000720
+ARM-NEXT: 0x188 IMAGE_REL_ARM_ADDR32NB $R000750
diff --git a/test/tools/llvm-cvtres/object.test b/test/tools/llvm-cvtres/object.test
index 8117ecc910c9..95522b17bd07 100644
--- a/test/tools/llvm-cvtres/object.test
+++ b/test/tools/llvm-cvtres/object.test
@@ -3,107 +3,138 @@
// rc.exe:
// > rc /fo test_resource.res /nologo test_resource.rc
// The object file we are comparing against was generated with this command using
-// the original cvtres.
-// > cvtres /machine:X86 /readonly /nologo /out:test_resource.o test_resource.res
+// the original Windows cvtres.exe.
+// > cvtres /machine:X86 /readonly /nologo /out:test_resource.obj.coff \
+// test_resource.res
-RUN: llvm-cvtres /out:%t %p/Inputs/test_resource.res
+RUN: llvm-cvtres /verbose /out:%t %p/Inputs/test_resource.res
RUN: llvm-readobj -coff-resources -section-data %t | FileCheck %s
-CHECK: Resources [
-CHECK-NEXT: String Name Entries: 1
-CHECK-NEXT: ID Entries: 4
-CHECK-NEXT: Type: STRINGARRAY [
-CHECK-NEXT: String Name Entries: 1
-CHECK-NEXT: ID Entries: 0
-CHECK-NEXT: Name: MYRESOURCE [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 1033) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: Type: kRT_BITMAP (ID 2) [
-CHECK-NEXT: String Name Entries: 2
-CHECK-NEXT: ID Entries: 0
-CHECK-NEXT: Name: CURSOR [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 1033) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: Name: OKAY [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 1033) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: Type: kRT_MENU (ID 4) [
-CHECK-NEXT: String Name Entries: 1
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Name: "EAT" [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 3081) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: Name: (ID 14432) [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 2052) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: Type: kRT_DIALOG (ID 5) [
-CHECK-NEXT: String Name Entries: 1
-CHECK-NEXT: ID Entries: 0
-CHECK-NEXT: Name: TESTDIALOG [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 1033) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: Type: kRT_ACCELERATOR (ID 9) [
-CHECK-NEXT: String Name Entries: 1
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Name: MYACCELERATORS [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 1033) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: Name: (ID 12) [
-CHECK-NEXT: String Name Entries: 0
-CHECK-NEXT: ID Entries: 1
-CHECK-NEXT: Language: (ID 1033) [
-CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-CHECK-NEXT: Major Version: 0
-CHECK-NEXT: Minor Version: 0
-CHECK-NEXT: ]
-CHECK-NEXT: ]
-CHECK-NEXT: ]
+CHECK: Resources [
+CHECK-NEXT: Total Number of Resources: 8
+CHECK-DAG: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 4
+CHECK-NEXT: Type: STRINGARRAY [
+CHECK-NEXT: Table Offset: 0x38
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 0
+CHECK-NEXT: Name: MYRESOURCE [
+CHECK-NEXT: Table Offset: 0xC8
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x188
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_BITMAP (ID 2) [
+CHECK-NEXT: Table Offset: 0x50
+CHECK-NEXT: Number of String Entries: 2
+CHECK-NEXT: Number of ID Entries: 0
+CHECK-NEXT: Name: CURSOR [
+CHECK-NEXT: Table Offset: 0xE0
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x198
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Name: OKAY [
+CHECK-NEXT: Table Offset: 0xF8
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x1A8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_MENU (ID 4) [
+CHECK-NEXT: Table Offset: 0x70
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Name: "EAT" [
+CHECK-NEXT: Table Offset: 0x110
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 3081) [
+CHECK-NEXT: Entry Offset: 0x1B8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Name: (ID 14432) [
+CHECK-NEXT: Table Offset: 0x128
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 2052) [
+CHECK-NEXT: Entry Offset: 0x1C8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_DIALOG (ID 5) [
+CHECK-NEXT: Table Offset: 0x90
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 0
+CHECK-NEXT: Name: TESTDIALOG [
+CHECK-NEXT: Table Offset: 0x140
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x1D8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Type: kRT_ACCELERATOR (ID 9) [
+CHECK-NEXT: Table Offset: 0xA8
+CHECK-NEXT: Number of String Entries: 1
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Name: MYACCELERATORS [
+CHECK-NEXT: Table Offset: 0x158
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x1E8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: Name: (ID 12) [
+CHECK-NEXT: Table Offset: 0x170
+CHECK-NEXT: Number of String Entries: 0
+CHECK-NEXT: Number of ID Entries: 1
+CHECK-NEXT: Language: (ID 1033) [
+CHECK-NEXT: Entry Offset: 0x1F8
+CHECK-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+CHECK-NEXT: Major Version: 0
+CHECK-NEXT: Minor Version: 0
+CHECK-NEXT: Characteristics: 0
+CHECK-NEXT: ]
+CHECK-NEXT: ]
+CHECK-NEXT: ]
CHECK-DAG: .rsrc$02 Data (
CHECK-NEXT: 0000: 11000300 E7030000 0D004400 4C040000 |..........D.L...|
CHECK-NEXT: 0010: 82001200 BC010000 28000000 10000000 |........(.......|
diff --git a/test/tools/llvm-cvtres/parse.test b/test/tools/llvm-cvtres/parse.test
index 23911ada82e8..c8b3d227f0b5 100644
--- a/test/tools/llvm-cvtres/parse.test
+++ b/test/tools/llvm-cvtres/parse.test
@@ -2,7 +2,7 @@
// rc.exe:
// > rc /fo test_resource.res /nologo test_resource.rc
-RUN: llvm-cvtres /verbose /out:%t %p/Inputs/test_resource.res | FileCheck %s
+RUN: llvm-cvtres /out:%t /verbose %p/Inputs/test_resource.res | FileCheck %s
CHECK: Number of resources: 8
CHECK-NEXT: Resource Tree [
diff --git a/test/tools/llvm-dwarfdump/X86/apple_names_verify_buckets.s b/test/tools/llvm-dwarfdump/X86/apple_names_verify_buckets.s
new file mode 100644
index 000000000000..903153c79a48
--- /dev/null
+++ b/test/tools/llvm-dwarfdump/X86/apple_names_verify_buckets.s
@@ -0,0 +1,192 @@
+# RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \
+# RUN: | not llvm-dwarfdump -verify - \
+# RUN: | FileCheck %s
+
+# CHECK: Verifying .apple_names...
+# CHECK-NEXT: error:
+
+# This test is meant to verify that the -verify option
+# in llvm-dwarfdump, correctly identifies
+# an invalid hash index for bucket[0] in the .apple_names section.
+
+ .section __TEXT,__text,regular,pure_instructions
+ .file 1 "basic.c"
+ .comm _i,4,2 ## @i
+ .section __DWARF,__debug_str,regular,debug
+Linfo_string:
+ .asciz "basic.c" ## string offset=42
+ .asciz "i" ## string offset=84
+ .asciz "int" ## string offset=86
+ .section __DWARF,__debug_loc,regular,debug
+Lsection_debug_loc:
+ .section __DWARF,__debug_abbrev,regular,debug
+Lsection_abbrev:
+ .byte 1 ## Abbreviation Code
+ .byte 17 ## DW_TAG_compile_unit
+ .byte 1 ## DW_CHILDREN_yes
+ .byte 37 ## DW_AT_producer
+ .byte 14 ## DW_FORM_strp
+ .byte 19 ## DW_AT_language
+ .byte 5 ## DW_FORM_data2
+ .byte 3 ## DW_AT_name
+ .byte 14 ## DW_FORM_strp
+ .byte 16 ## DW_AT_stmt_list
+ .byte 23 ## DW_FORM_sec_offset
+ .byte 27 ## DW_AT_comp_dir
+ .byte 14 ## DW_FORM_strp
+ .byte 0 ## EOM(1)
+ .byte 0 ## EOM(2)
+ .byte 2 ## Abbreviation Code
+ .byte 52 ## DW_TAG_variable
+ .byte 0 ## DW_CHILDREN_no
+ .byte 3 ## DW_AT_name
+ .byte 14 ## DW_FORM_strp
+ .byte 73 ## DW_AT_type
+ .byte 19 ## DW_FORM_ref4
+ .byte 63 ## DW_AT_external
+ .byte 25 ## DW_FORM_flag_present
+ .byte 58 ## DW_AT_decl_file
+ .byte 11 ## DW_FORM_data1
+ .byte 59 ## DW_AT_decl_line
+ .byte 11 ## DW_FORM_data1
+ .byte 2 ## DW_AT_location
+ .byte 24 ## DW_FORM_exprloc
+ .byte 0 ## EOM(1)
+ .byte 0 ## EOM(2)
+ .byte 3 ## Abbreviation Code
+ .byte 36 ## DW_TAG_base_type
+ .byte 0 ## DW_CHILDREN_no
+ .byte 3 ## DW_AT_name
+ .byte 14 ## DW_FORM_strp
+ .byte 62 ## DW_AT_encoding
+ .byte 11 ## DW_FORM_data1
+ .byte 11 ## DW_AT_byte_size
+ .byte 11 ## DW_FORM_data1
+ .byte 0 ## EOM(1)
+ .byte 0 ## EOM(2)
+ .byte 0 ## EOM(3)
+ .section __DWARF,__debug_info,regular,debug
+Lsection_info:
+Lcu_begin0:
+ .long 55 ## Length of Unit
+ .short 4 ## DWARF version number
+Lset0 = Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section
+ .long Lset0
+ .byte 8 ## Address Size (in bytes)
+ .byte 1 ## Abbrev [1] 0xb:0x30 DW_TAG_compile_unit
+ .long 0 ## DW_AT_producer
+ .short 12 ## DW_AT_language
+ .long 42 ## DW_AT_name
+Lset1 = Lline_table_start0-Lsection_line ## DW_AT_stmt_list
+ .long Lset1
+ .long 50 ## DW_AT_comp_dir
+ .byte 2 ## Abbrev [2] 0x1e:0x15 DW_TAG_variable
+ .long 84 ## DW_AT_name
+ .long 51 ## DW_AT_type
+ ## DW_AT_external
+ .byte 1 ## DW_AT_decl_file
+ .byte 1 ## DW_AT_decl_line
+ .byte 9 ## DW_AT_location
+ .byte 3
+ .quad _i
+ .byte 3 ## Abbrev [3] 0x33:0x7 DW_TAG_base_type
+ .long 86 ## DW_AT_name
+ .byte 5 ## DW_AT_encoding
+ .byte 4 ## DW_AT_byte_size
+ .byte 0 ## End Of Children Mark
+ .section __DWARF,__debug_ranges,regular,debug
+Ldebug_range:
+ .section __DWARF,__debug_macinfo,regular,debug
+Ldebug_macinfo:
+Lcu_macro_begin0:
+ .byte 0 ## End Of Macro List Mark
+ .section __DWARF,__apple_names,regular,debug
+Lnames_begin:
+ .long 1212240712 ## Header Magic
+ .short 1 ## Header Version
+ .short 0 ## Header Hash Function
+ .long 1 ## Header Bucket Count
+ .long 1 ## Header Hash Count
+ .long 12 ## Header Data Length
+ .long 0 ## HeaderData Die Offset Base
+ .long 1 ## HeaderData Atom Count
+ .short 1 ## DW_ATOM_die_offset
+ .short 6 ## DW_FORM_data4
+ .long -2 ## Bucket 0 -- error: Bucket[0] has invalid hash index: [-2]
+ .long 177678 ## Hash in Bucket 0
+ .long LNames0-Lnames_begin ## Offset in Bucket 0
+LNames0:
+ .long 84 ## i
+ .long 1 ## Num DIEs
+ .long 30
+ .long 0
+ .section __DWARF,__apple_objc,regular,debug
+Lobjc_begin:
+ .long 1212240712 ## Header Magic
+ .short 1 ## Header Version
+ .short 0 ## Header Hash Function
+ .long 1 ## Header Bucket Count
+ .long 0 ## Header Hash Count
+ .long 12 ## Header Data Length
+ .long 0 ## HeaderData Die Offset Base
+ .long 1 ## HeaderData Atom Count
+ .short 1 ## DW_ATOM_die_offset
+ .short 6 ## DW_FORM_data4
+ .long -1 ## Bucket 0
+ .section __DWARF,__apple_namespac,regular,debug
+Lnamespac_begin:
+ .long 1212240712 ## Header Magic
+ .short 1 ## Header Version
+ .short 0 ## Header Hash Function
+ .long 1 ## Header Bucket Count
+ .long 0 ## Header Hash Count
+ .long 12 ## Header Data Length
+ .long 0 ## HeaderData Die Offset Base
+ .long 1 ## HeaderData Atom Count
+ .short 1 ## DW_ATOM_die_offset
+ .short 6 ## DW_FORM_data4
+ .long -1 ## Bucket 0
+ .section __DWARF,__apple_types,regular,debug
+Ltypes_begin:
+ .long 1212240712 ## Header Magic
+ .short 1 ## Header Version
+ .short 0 ## Header Hash Function
+ .long 1 ## Header Bucket Count
+ .long 1 ## Header Hash Count
+ .long 20 ## Header Data Length
+ .long 0 ## HeaderData Die Offset Base
+ .long 3 ## HeaderData Atom Count
+ .short 1 ## DW_ATOM_die_offset
+ .short 6 ## DW_FORM_data4
+ .short 3 ## DW_ATOM_die_tag
+ .short 5 ## DW_FORM_data2
+ .short 4 ## DW_ATOM_type_flags
+ .short 11 ## DW_FORM_data1
+ .long 0 ## Bucket 0
+ .long 193495088 ## Hash in Bucket 0
+ .long Ltypes0-Ltypes_begin ## Offset in Bucket 0
+Ltypes0:
+ .long 86 ## int
+ .long 1 ## Num DIEs
+ .long 51
+ .short 36
+ .byte 0
+ .long 0
+ .section __DWARF,__apple_exttypes,regular,debug
+Lexttypes_begin:
+ .long 1212240712 ## Header Magic
+ .short 1 ## Header Version
+ .short 0 ## Header Hash Function
+ .long 1 ## Header Bucket Count
+ .long 0 ## Header Hash Count
+ .long 12 ## Header Data Length
+ .long 0 ## HeaderData Die Offset Base
+ .long 1 ## HeaderData Atom Count
+ .short 7 ## DW_ATOM_ext_types
+ .short 6 ## DW_FORM_data4
+ .long -1 ## Bucket 0
+
+.subsections_via_symbols
+ .section __DWARF,__debug_line,regular,debug
+Lsection_line:
+Lline_table_start0:
diff --git a/test/tools/llvm-pdbdump/raw-stream-data.test b/test/tools/llvm-pdbdump/raw-stream-data.test
deleted file mode 100644
index 1d7c23fe3672..000000000000
--- a/test/tools/llvm-pdbdump/raw-stream-data.test
+++ /dev/null
@@ -1,47 +0,0 @@
-; RUN: llvm-pdbutil raw -stream-data=8 %p/Inputs/LoadAddressTest.pdb \
-; RUN: | FileCheck %s -check-prefix=FULL_STREAM
-; RUN: llvm-pdbutil raw -stream-data=8:4 %p/Inputs/LoadAddressTest.pdb \
-; RUN: | FileCheck %s -check-prefix=OFFSET_STREAM
-; RUN: llvm-pdbutil raw -stream-data=8:4@24 %p/Inputs/LoadAddressTest.pdb \
-; RUN: | FileCheck %s -check-prefix=OFFSET_AND_LENGTH
-
-FULL_STREAM: Stream Data {
-FULL_STREAM-NEXT: Stream {
-FULL_STREAM-NEXT: Index: 8
-FULL_STREAM-NEXT: Type: Public Symbol Records
-FULL_STREAM-NEXT: Size: 40
-FULL_STREAM-NEXT: Blocks:
-FULL_STREAM-NEXT: Data (
-FULL_STREAM-NEXT: 0000: 12000E11 02000000 10000000 01005F6D |.............._m|
-FULL_STREAM-NEXT: 0010: 61696E00 12002511 00000000 88000000 |ain...%.........|
-FULL_STREAM-NEXT: 0020: 01006D61 696E0000 |..main..|
-FULL_STREAM-NEXT: )
-FULL_STREAM-NEXT: }
-FULL_STREAM-NEXT: }
-
-OFFSET_STREAM: Stream Data {
-OFFSET_STREAM-NEXT: Stream {
-OFFSET_STREAM-NEXT: Index: 8
-OFFSET_STREAM-NEXT: Type: Public Symbol Records
-OFFSET_STREAM-NEXT: Size: 40
-OFFSET_STREAM-NEXT: Blocks:
-OFFSET_STREAM-NEXT: Data (
-OFFSET_STREAM-NEXT: 0004: 02000000 10000000 01005F6D 61696E00 |.........._main.|
-OFFSET_STREAM-NEXT: 0014: 12002511 00000000 88000000 01006D61 |..%...........ma|
-OFFSET_STREAM-NEXT: 0024: 696E0000 |in..|
-OFFSET_STREAM-NEXT: )
-OFFSET_STREAM-NEXT: }
-OFFSET_STREAM-NEXT:}
-
-OFFSET_AND_LENGTH: Stream Data {
-OFFSET_AND_LENGTH-NEXT: Stream {
-OFFSET_AND_LENGTH-NEXT: Index: 8
-OFFSET_AND_LENGTH-NEXT: Type: Public Symbol Records
-OFFSET_AND_LENGTH-NEXT: Size: 40
-OFFSET_AND_LENGTH-NEXT: Blocks:
-OFFSET_AND_LENGTH-NEXT: Data (
-OFFSET_AND_LENGTH-NEXT: 0004: 02000000 10000000 01005F6D 61696E00 |.........._main.|
-OFFSET_AND_LENGTH-NEXT: 0014: 12002511 00000000 |..%.....|
-OFFSET_AND_LENGTH-NEXT: )
-OFFSET_AND_LENGTH-NEXT: }
-OFFSET_AND_LENGTH-NEXT:} \ No newline at end of file
diff --git a/test/tools/llvm-readobj/resources.test b/test/tools/llvm-readobj/resources.test
index 855ce5393b84..589a9c968aae 100644
--- a/test/tools/llvm-readobj/resources.test
+++ b/test/tools/llvm-readobj/resources.test
@@ -9,103 +9,135 @@ RUN: | FileCheck %s -check-prefix ZERO
RUN: llvm-readobj -coff-resources %p/Inputs/resources/test_resource.obj.coff \
RUN: | FileCheck %s -check-prefix TEST_RES
-ZERO: Resources [
-ZERO-NEXT: String Name Entries: 0
-ZERO-NEXT: ID Entries: 1
-ZERO-NEXT: Type: kRT_STRING (ID 6) [
-ZERO-NEXT: String Name Entries: 0
-ZERO-NEXT: ID Entries: 1
-ZERO-NEXT: Name: (ID 1) [
-ZERO-NEXT: String Name Entries: 0
-ZERO-NEXT: ID Entries: 1
-ZERO-NEXT: Language: (ID 1033) [
-ZERO-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-ZERO-NEXT: Major Version: 0
-ZERO-NEXT: Minor Version: 0
-ZERO-NEXT: ]
-ZERO-NEXT: ]
-ZERO-NEXT: ]
+ZERO: Resources [
+ZERO-NEXT: Total Number of Resources: 1
+ZERO-NEXT: Base Table Address: 0x188
+ZERO-DAG: Number of String Entries: 0
+ZERO-NEXT: Number of ID Entries: 1
+ZERO-NEXT: Type: kRT_STRING (ID 6) [
+ZERO-NEXT: Table Offset: 0x18
+ZERO-NEXT: Number of String Entries: 0
+ZERO-NEXT: Number of ID Entries: 1
+ZERO-NEXT: Name: (ID 1) [
+ZERO-NEXT: Table Offset: 0x30
+ZERO-NEXT: Number of String Entries: 0
+ZERO-NEXT: Number of ID Entries: 1
+ZERO-NEXT: Language: (ID 1033) [
+ZERO-NEXT: Entry Offset: 0x48
+ZERO-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+ZERO-NEXT: Major Version: 0
+ZERO-NEXT: Minor Version: 0
+ZERO-NEXT: Characteristics: 0
+ZERO-NEXT: ]
+ZERO-NEXT: ]
+ZERO-NEXT: ]
-
-TEST_RES: Resources [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 4
-TEST_RES-NEXT: Type: kRT_BITMAP (ID 2) [
-TEST_RES-NEXT: String Name Entries: 2
-TEST_RES-NEXT: ID Entries: 0
-TEST_RES-NEXT: Name: CURSOR [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Language: (ID 1033) [
-TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-TEST_RES-NEXT: Major Version: 0
-TEST_RES-NEXT: Minor Version: 0
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: Name: OKAY [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Language: (ID 1033) [
-TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-TEST_RES-NEXT: Major Version: 0
-TEST_RES-NEXT: Minor Version: 0
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: Type: kRT_MENU (ID 4) [
-TEST_RES-NEXT: String Name Entries: 1
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Name: "EAT" [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Language: (ID 3081) [
-TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-TEST_RES-NEXT: Major Version: 0
-TEST_RES-NEXT: Minor Version: 0
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: Name: (ID 14432) [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Language: (ID 2052) [
-TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-TEST_RES-NEXT: Major Version: 0
-TEST_RES-NEXT: Minor Version: 0
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: Type: kRT_DIALOG (ID 5) [
-TEST_RES-NEXT: String Name Entries: 1
-TEST_RES-NEXT: ID Entries: 0
-TEST_RES-NEXT: Name: TESTDIALOG [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Language: (ID 1033) [
-TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-TEST_RES-NEXT: Major Version: 0
-TEST_RES-NEXT: Minor Version: 0
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: Type: kRT_ACCELERATOR (ID 9) [
-TEST_RES-NEXT: String Name Entries: 1
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Name: MYACCELERATORS [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Language: (ID 1033) [
-TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-TEST_RES-NEXT: Major Version: 0
-TEST_RES-NEXT: Minor Version: 0
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: Name: (ID 12) [
-TEST_RES-NEXT: String Name Entries: 0
-TEST_RES-NEXT: ID Entries: 1
-TEST_RES-NEXT: Language: (ID 1033) [
-TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
-TEST_RES-NEXT: Major Version: 0
-TEST_RES-NEXT: Minor Version: 0
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
-TEST_RES-NEXT: ]
+TEST_RES: Resources [
+TEST_RES-NEXT: Total Number of Resources: 7
+TEST_RES-NEXT: Base Table Address: 0x1C0
+TEST_RES-DAG: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 4
+TEST_RES-NEXT: Type: kRT_BITMAP (ID 2) [
+TEST_RES-NEXT: Table Offset: 0x30
+TEST_RES-NEXT: Number of String Entries: 2
+TEST_RES-NEXT: Number of ID Entries: 0
+TEST_RES-NEXT: Name: CURSOR [
+TEST_RES-NEXT: Table Offset: 0xA8
+TEST_RES-NEXT: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Language: (ID 1033) [
+TEST_RES-NEXT: Entry Offset: 0x150
+TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+TEST_RES-NEXT: Major Version: 0
+TEST_RES-NEXT: Minor Version: 0
+TEST_RES-NEXT: Characteristics: 0
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: Name: OKAY [
+TEST_RES-NEXT: Table Offset: 0xC0
+TEST_RES-NEXT: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Language: (ID 1033) [
+TEST_RES-NEXT: Entry Offset: 0x160
+TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+TEST_RES-NEXT: Major Version: 0
+TEST_RES-NEXT: Minor Version: 0
+TEST_RES-NEXT: Characteristics: 0
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: Type: kRT_MENU (ID 4) [
+TEST_RES-NEXT: Table Offset: 0x50
+TEST_RES-NEXT: Number of String Entries: 1
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Name: "EAT" [
+TEST_RES-NEXT: Table Offset: 0xD8
+TEST_RES-NEXT: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Language: (ID 3081) [
+TEST_RES-NEXT: Entry Offset: 0x170
+TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+TEST_RES-NEXT: Major Version: 0
+TEST_RES-NEXT: Minor Version: 0
+TEST_RES-NEXT: Characteristics: 0
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: Name: (ID 14432) [
+TEST_RES-NEXT: Table Offset: 0xF0
+TEST_RES-NEXT: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Language: (ID 2052) [
+TEST_RES-NEXT: Entry Offset: 0x180
+TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+TEST_RES-NEXT: Major Version: 0
+TEST_RES-NEXT: Minor Version: 0
+TEST_RES-NEXT: Characteristics: 0
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: Type: kRT_DIALOG (ID 5) [
+TEST_RES-NEXT: Table Offset: 0x70
+TEST_RES-NEXT: Number of String Entries: 1
+TEST_RES-NEXT: Number of ID Entries: 0
+TEST_RES-NEXT: Name: TESTDIALOG [
+TEST_RES-NEXT: Table Offset: 0x108
+TEST_RES-NEXT: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Language: (ID 1033) [
+TEST_RES-NEXT: Entry Offset: 0x190
+TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+TEST_RES-NEXT: Major Version: 0
+TEST_RES-NEXT: Minor Version: 0
+TEST_RES-NEXT: Characteristics: 0
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: Type: kRT_ACCELERATOR (ID 9) [
+TEST_RES-NEXT: Table Offset: 0x88
+TEST_RES-NEXT: Number of String Entries: 1
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Name: MYACCELERATORS [
+TEST_RES-NEXT: Table Offset: 0x120
+TEST_RES-NEXT: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Language: (ID 1033) [
+TEST_RES-NEXT: Entry Offset: 0x1A0
+TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+TEST_RES-NEXT: Major Version: 0
+TEST_RES-NEXT: Minor Version: 0
+TEST_RES-NEXT: Characteristics: 0
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: Name: (ID 12) [
+TEST_RES-NEXT: Table Offset: 0x138
+TEST_RES-NEXT: Number of String Entries: 0
+TEST_RES-NEXT: Number of ID Entries: 1
+TEST_RES-NEXT: Language: (ID 1033) [
+TEST_RES-NEXT: Entry Offset: 0x1B0
+TEST_RES-NEXT: Time/Date Stamp: 1970-01-01 00:00:00 (0x0)
+TEST_RES-NEXT: Major Version: 0
+TEST_RES-NEXT: Minor Version: 0
+TEST_RES-NEXT: Characteristics: 0
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
+TEST_RES-NEXT: ]
diff --git a/tools/llvm-ar/llvm-ar.cpp b/tools/llvm-ar/llvm-ar.cpp
index 3de260410bd9..500507fd4966 100644
--- a/tools/llvm-ar/llvm-ar.cpp
+++ b/tools/llvm-ar/llvm-ar.cpp
@@ -473,6 +473,10 @@ static void addMember(std::vector<NewArchiveMember> &Members,
Expected<NewArchiveMember> NMOrErr =
NewArchiveMember::getFile(FileName, Deterministic);
failIfError(NMOrErr.takeError(), FileName);
+
+ // Use the basename of the object path for the member name.
+ NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
+
if (Pos == -1)
Members.push_back(std::move(*NMOrErr));
else
@@ -494,7 +498,7 @@ static void addMember(std::vector<NewArchiveMember> &Members,
enum InsertAction {
IA_AddOldMember,
- IA_AddNewMeber,
+ IA_AddNewMember,
IA_Delete,
IA_MoveOldMember,
IA_MoveNewMember
@@ -526,7 +530,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
StringRef PosName = sys::path::filename(RelPos);
if (!OnlyUpdate) {
if (PosName.empty())
- return IA_AddNewMeber;
+ return IA_AddNewMember;
return IA_MoveNewMember;
}
@@ -543,7 +547,7 @@ static InsertAction computeInsertAction(ArchiveOperation Operation,
}
if (PosName.empty())
- return IA_AddNewMeber;
+ return IA_AddNewMember;
return IA_MoveNewMember;
}
llvm_unreachable("No such operation");
@@ -580,7 +584,7 @@ computeNewArchiveMembers(ArchiveOperation Operation,
case IA_AddOldMember:
addMember(Ret, Child);
break;
- case IA_AddNewMeber:
+ case IA_AddNewMember:
addMember(Ret, *MemberI);
break;
case IA_Delete:
diff --git a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index c8fa56d724bf..22bc6f7043ee 100644
--- a/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -320,6 +320,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FS, TYPE_TEST_ASSUME_CONST_VCALL)
STRINGIFY_CODE(FS, TYPE_CHECKED_LOAD_CONST_VCALL)
STRINGIFY_CODE(FS, VALUE_GUID)
+ STRINGIFY_CODE(FS, CFI_FUNCTION_DEFS)
+ STRINGIFY_CODE(FS, CFI_FUNCTION_DECLS)
}
case bitc::METADATA_ATTACHMENT_ID:
switch(CodeID) {
diff --git a/tools/llvm-cvtres/llvm-cvtres.cpp b/tools/llvm-cvtres/llvm-cvtres.cpp
index eaba02c16f39..1e463399a598 100644
--- a/tools/llvm-cvtres/llvm-cvtres.cpp
+++ b/tools/llvm-cvtres/llvm-cvtres.cpp
@@ -191,11 +191,23 @@ int main(int argc_, const char *argv_[]) {
error(Parser.parse(RF));
}
- if (Verbose)
- Parser.printTree();
+ if (Verbose) {
+ Parser.printTree(outs());
+ Parser.printTree(errs());
+ }
error(
llvm::object::writeWindowsResourceCOFF(OutputFile, MachineType, Parser));
+ if (Verbose) {
+ Expected<object::OwningBinary<object::Binary>> BinaryOrErr =
+ object::createBinary(OutputFile);
+ if (!BinaryOrErr)
+ reportError(OutputFile, errorToErrorCode(BinaryOrErr.takeError()));
+ Binary &Binary = *BinaryOrErr.get().getBinary();
+ ScopedPrinter W(errs());
+ W.printBinaryBlock("Output File Raw Data", Binary.getData());
+ }
+
return 0;
}
diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 1da157c4e4d5..ec5e554d4f5f 100644
--- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -99,6 +99,7 @@ static void DumpObjectFile(ObjectFile &Obj, Twine Filename) {
outs() << Filename.str() << ":\tfile format " << Obj.getFileFormatName()
<< "\n\n";
+
// Dump the complete DWARF structure.
DIDumpOptions DumpOpts;
DumpOpts.DumpType = DumpType;
diff --git a/tools/llvm-pdbutil/CMakeLists.txt b/tools/llvm-pdbutil/CMakeLists.txt
index 9875dfb5a257..d09fa31d8b6a 100644
--- a/tools/llvm-pdbutil/CMakeLists.txt
+++ b/tools/llvm-pdbutil/CMakeLists.txt
@@ -12,8 +12,10 @@ add_llvm_tool(llvm-pdbutil
CompactTypeDumpVisitor.cpp
Diff.cpp
llvm-pdbutil.cpp
+ FormatUtil.cpp
LinePrinter.cpp
- LLVMOutputStyle.cpp
+ MinimalSymbolDumper.cpp
+ MinimalTypeDumper.cpp
PdbYaml.cpp
PrettyBuiltinDumper.cpp
PrettyClassDefinitionDumper.cpp
@@ -25,6 +27,7 @@ add_llvm_tool(llvm-pdbutil
PrettyTypeDumper.cpp
PrettyTypedefDumper.cpp
PrettyVariableDumper.cpp
+ RawOutputStyle.cpp
StreamUtil.cpp
YAMLOutputStyle.cpp
)
diff --git a/tools/llvm-pdbutil/FormatUtil.cpp b/tools/llvm-pdbutil/FormatUtil.cpp
new file mode 100644
index 000000000000..1bbe2724f0ab
--- /dev/null
+++ b/tools/llvm-pdbutil/FormatUtil.cpp
@@ -0,0 +1,49 @@
+//===- FormatUtil.cpp ----------------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FormatUtil.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::pdb;
+
+std::string llvm::pdb::typesetItemList(ArrayRef<std::string> Opts,
+ uint32_t IndentLevel, uint32_t GroupSize,
+ StringRef Sep) {
+ std::string Result;
+ while (!Opts.empty()) {
+ ArrayRef<std::string> ThisGroup;
+ ThisGroup = Opts.take_front(GroupSize);
+ Opts = Opts.drop_front(ThisGroup.size());
+ Result += join(ThisGroup, Sep);
+ if (!Opts.empty()) {
+ Result += Sep;
+ Result += "\n";
+ Result += formatv("{0}", fmt_repeat(' ', IndentLevel));
+ }
+ }
+ return Result;
+}
+
+std::string llvm::pdb::typesetStringList(uint32_t IndentLevel,
+ ArrayRef<StringRef> Strings) {
+ std::string Result = "[";
+ for (const auto &S : Strings) {
+ Result += formatv("\n{0}{1}", fmt_repeat(' ', IndentLevel), S);
+ }
+ Result += "]";
+ return Result;
+}
+
+std::string llvm::pdb::formatSegmentOffset(uint16_t Segment, uint32_t Offset) {
+ return formatv("{0:4}:{1:4}", Segment, Offset);
+}
diff --git a/tools/llvm-pdbutil/FormatUtil.h b/tools/llvm-pdbutil/FormatUtil.h
new file mode 100644
index 000000000000..3db2dbacc57b
--- /dev/null
+++ b/tools/llvm-pdbutil/FormatUtil.h
@@ -0,0 +1,120 @@
+//===- FormatUtil.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_TOOLS_LLVMPDBUTIL_FORMAT_UTIL_H
+#define LLVM_TOOLS_LLVMPDBUTIL_FORMAT_UTIL_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#include <string>
+#include <type_traits>
+
+namespace llvm {
+namespace pdb {
+
+#define PUSH_MASKED_FLAG(Enum, Mask, TheOpt, Value, Text) \
+ if (Enum::TheOpt == (Value & Mask)) \
+ Opts.push_back(Text);
+
+#define PUSH_FLAG(Enum, TheOpt, Value, Text) \
+ PUSH_MASKED_FLAG(Enum, Enum::TheOpt, TheOpt, Value, Text)
+
+#define RETURN_CASE(Enum, X, Ret) \
+ case Enum::X: \
+ return Ret;
+
+template <typename T> static std::string formatUnknownEnum(T Value) {
+ return formatv("unknown ({0})",
+ static_cast<typename std::underlying_type<T>::type>(Value))
+ .str();
+}
+
+std::string formatSegmentOffset(uint16_t Segment, uint32_t Offset);
+
+std::string typesetItemList(ArrayRef<std::string> Opts, uint32_t IndentLevel,
+ uint32_t GroupSize, StringRef Sep);
+
+std::string typesetStringList(uint32_t IndentLevel,
+ ArrayRef<StringRef> Strings);
+
+/// Returns the number of digits in the given integer.
+inline int NumDigits(uint64_t N) {
+ if (N < 10ULL)
+ return 1;
+ if (N < 100ULL)
+ return 2;
+ if (N < 1000ULL)
+ return 3;
+ if (N < 10000ULL)
+ return 4;
+ if (N < 100000ULL)
+ return 5;
+ if (N < 1000000ULL)
+ return 6;
+ if (N < 10000000ULL)
+ return 7;
+ if (N < 100000000ULL)
+ return 8;
+ if (N < 1000000000ULL)
+ return 9;
+ if (N < 10000000000ULL)
+ return 10;
+ if (N < 100000000000ULL)
+ return 11;
+ if (N < 1000000000000ULL)
+ return 12;
+ if (N < 10000000000000ULL)
+ return 13;
+ if (N < 100000000000000ULL)
+ return 14;
+ if (N < 1000000000000000ULL)
+ return 15;
+ if (N < 10000000000000000ULL)
+ return 16;
+ if (N < 100000000000000000ULL)
+ return 17;
+ if (N < 1000000000000000000ULL)
+ return 18;
+ if (N < 10000000000000000000ULL)
+ return 19;
+ return 20;
+}
+
+namespace detail {
+template <typename T>
+struct EndianAdapter final
+ : public FormatAdapter<support::detail::packed_endian_specific_integral<
+ T, support::little, support::unaligned>> {
+ using EndianType =
+ support::detail::packed_endian_specific_integral<T, support::little,
+ support::unaligned>;
+
+ explicit EndianAdapter(EndianType &&Item)
+ : FormatAdapter<EndianType>(std::move(Item)) {}
+
+ void format(llvm::raw_ostream &Stream, StringRef Style) {
+ format_provider<T>::format(static_cast<T>(this->Item), Stream, Style);
+ }
+};
+} // namespace detail
+
+template <typename T>
+detail::EndianAdapter<T>
+fmtle(support::detail::packed_endian_specific_integral<T, support::little,
+ support::unaligned>
+ Value) {
+ return detail::EndianAdapter<T>(std::move(Value));
+}
+}
+} // namespace llvm
+#endif
diff --git a/tools/llvm-pdbutil/LLVMOutputStyle.cpp b/tools/llvm-pdbutil/LLVMOutputStyle.cpp
deleted file mode 100644
index 824f88f8efd0..000000000000
--- a/tools/llvm-pdbutil/LLVMOutputStyle.cpp
+++ /dev/null
@@ -1,1188 +0,0 @@
-//===- LLVMOutputStyle.cpp ------------------------------------ *- C++ --*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LLVMOutputStyle.h"
-
-#include "CompactTypeDumpVisitor.h"
-#include "StreamUtil.h"
-#include "llvm-pdbutil.h"
-
-#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
-#include "llvm/DebugInfo/CodeView/DebugSymbolRVASubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
-#include "llvm/DebugInfo/CodeView/EnumTables.h"
-#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
-#include "llvm/DebugInfo/CodeView/Line.h"
-#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
-#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
-#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
-#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
-#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
-#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
-#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
-#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
-#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
-#include "llvm/DebugInfo/PDB/Native/RawError.h"
-#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
-#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
-#include "llvm/DebugInfo/PDB/PDBExtras.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Support/BinaryStreamReader.h"
-#include "llvm/Support/FormatVariadic.h"
-
-#include <unordered_map>
-
-using namespace llvm;
-using namespace llvm::codeview;
-using namespace llvm::msf;
-using namespace llvm::pdb;
-
-namespace {
-struct PageStats {
- explicit PageStats(const BitVector &FreePages)
- : Upm(FreePages), ActualUsedPages(FreePages.size()),
- MultiUsePages(FreePages.size()), UseAfterFreePages(FreePages.size()) {
- const_cast<BitVector &>(Upm).flip();
- // To calculate orphaned pages, we start with the set of pages that the
- // MSF thinks are used. Each time we find one that actually *is* used,
- // we unset it. Whichever bits remain set at the end are orphaned.
- OrphanedPages = Upm;
- }
-
- // The inverse of the MSF File's copy of the Fpm. The basis for which we
- // determine the allocation status of each page.
- const BitVector Upm;
-
- // Pages which are marked as used in the FPM and are used at least once.
- BitVector ActualUsedPages;
-
- // Pages which are marked as used in the FPM but are used more than once.
- BitVector MultiUsePages;
-
- // Pages which are marked as used in the FPM but are not used at all.
- BitVector OrphanedPages;
-
- // Pages which are marked free in the FPM but are used.
- BitVector UseAfterFreePages;
-};
-
-class C13RawVisitor : public DebugSubsectionVisitor {
-public:
- C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &TPI,
- LazyRandomTypeCollection &IPI)
- : P(P), TPI(TPI), IPI(IPI) {}
-
- Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::Unknown))
- return Error::success();
- DictScope DD(P, "Unknown");
- P.printHex("Kind", static_cast<uint32_t>(Unknown.kind()));
- ArrayRef<uint8_t> Data;
- BinaryStreamReader Reader(Unknown.getData());
- consumeError(Reader.readBytes(Data, Reader.bytesRemaining()));
- P.printBinaryBlock("Data", Data);
- return Error::success();
- }
-
- Error visitLines(DebugLinesSubsectionRef &Lines,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::Lines))
- return Error::success();
-
- DictScope DD(P, "Lines");
-
- P.printNumber("RelocSegment", Lines.header()->RelocSegment);
- P.printNumber("RelocOffset", Lines.header()->RelocOffset);
- P.printNumber("CodeSize", Lines.header()->CodeSize);
- P.printBoolean("HasColumns", Lines.hasColumnInfo());
-
- for (const auto &L : Lines) {
- DictScope DDDD(P, "FileEntry");
-
- if (auto EC = printFileName("FileName", L.NameIndex, State))
- return EC;
-
- for (const auto &N : L.LineNumbers) {
- DictScope DDD(P, "Line");
- LineInfo LI(N.Flags);
- P.printNumber("Offset", N.Offset);
- if (LI.isAlwaysStepInto())
- P.printString("StepInto", StringRef("Always"));
- else if (LI.isNeverStepInto())
- P.printString("StepInto", StringRef("Never"));
- else
- P.printNumber("LineNumberStart", LI.getStartLine());
- P.printNumber("EndDelta", LI.getLineDelta());
- P.printBoolean("IsStatement", LI.isStatement());
- }
- for (const auto &C : L.Columns) {
- DictScope DDD(P, "Column");
- P.printNumber("Start", C.StartColumn);
- P.printNumber("End", C.EndColumn);
- }
- }
-
- return Error::success();
- }
-
- Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums))
- return Error::success();
-
- DictScope DD(P, "FileChecksums");
- for (const auto &CS : Checksums) {
- DictScope DDD(P, "Checksum");
- if (auto Result = getNameFromStringTable(CS.FileNameOffset, State))
- P.printString("FileName", *Result);
- else
- return Result.takeError();
- P.printEnum("Kind", uint8_t(CS.Kind), getFileChecksumNames());
- P.printBinaryBlock("Checksum", CS.Checksum);
- }
- return Error::success();
- }
-
- Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines))
- return Error::success();
-
- DictScope D(P, "InlineeLines");
- P.printBoolean("HasExtraFiles", Inlinees.hasExtraFiles());
- ListScope LS(P, "Lines");
- for (const auto &L : Inlinees) {
- DictScope DDD(P, "Inlinee");
- if (auto EC = printFileName("FileName", L.Header->FileID, State))
- return EC;
-
- if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
- return EC;
- P.printNumber("SourceLine", L.Header->SourceLineNum);
- if (Inlinees.hasExtraFiles()) {
- ListScope DDDD(P, "ExtraFiles");
- for (const auto &EF : L.ExtraFiles) {
- if (auto EC = printFileName("File", EF, State))
- return EC;
- }
- }
- }
- return Error::success();
- }
-
- Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports))
- return Error::success();
-
- ListScope D(P, "CrossModuleExports");
- for (const auto &M : CSE) {
- DictScope D(P, "Export");
- P.printHex("Local", M.Local);
- P.printHex("Global", M.Global);
- }
- return Error::success();
- }
-
- Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSI,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports))
- return Error::success();
-
- ListScope L(P, "CrossModuleImports");
- for (const auto &M : CSI) {
- DictScope D(P, "ModuleImport");
- auto Name = getNameFromStringTable(M.Header->ModuleNameOffset, State);
- if (!Name)
- return Name.takeError();
- P.printString("Module", *Name);
- P.printHexList("Imports", M.Imports);
- }
- return Error::success();
- }
-
- Error visitFrameData(DebugFrameDataSubsectionRef &FD,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::FrameData))
- return Error::success();
-
- ListScope L(P, "FrameData");
- for (const auto &Frame : FD) {
- DictScope D(P, "Frame");
- auto Name = getNameFromStringTable(Frame.FrameFunc, State);
- if (!Name)
- return joinErrors(make_error<RawError>(raw_error_code::invalid_format,
- "Invalid Frame.FrameFunc index"),
- Name.takeError());
- P.printNumber("Rva", Frame.RvaStart);
- P.printNumber("CodeSize", Frame.CodeSize);
- P.printNumber("LocalSize", Frame.LocalSize);
- P.printNumber("ParamsSize", Frame.ParamsSize);
- P.printNumber("MaxStackSize", Frame.MaxStackSize);
- P.printString("FrameFunc", *Name);
- P.printNumber("PrologSize", Frame.PrologSize);
- P.printNumber("SavedRegsSize", Frame.SavedRegsSize);
- P.printNumber("Flags", Frame.Flags);
- }
- return Error::success();
- }
-
- Error visitSymbols(DebugSymbolsSubsectionRef &Symbols,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::Symbols))
- return Error::success();
- ListScope L(P, "Symbols");
-
- // This section should not actually appear in a PDB file, it really only
- // appears in object files. But we support it here for testing. So we
- // specify the Object File container type.
- codeview::CVSymbolDumper SD(P, TPI, CodeViewContainer::ObjectFile, nullptr,
- false);
- for (auto S : Symbols) {
- DictScope LL(P, "");
- if (auto EC = SD.dump(S)) {
- return make_error<RawError>(
- raw_error_code::corrupt_file,
- "DEBUG_S_SYMBOLS subsection contained corrupt symbol record");
- }
- }
- return Error::success();
- }
-
- Error visitStringTable(DebugStringTableSubsectionRef &Strings,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::StringTable))
- return Error::success();
-
- ListScope D(P, "String Table");
- BinaryStreamReader Reader(Strings.getBuffer());
- StringRef S;
- consumeError(Reader.readCString(S));
- while (Reader.bytesRemaining() > 0) {
- consumeError(Reader.readCString(S));
- if (S.empty() && Reader.bytesRemaining() < 4)
- break;
- P.printString(S);
- }
- return Error::success();
- }
-
- Error visitCOFFSymbolRVAs(DebugSymbolRVASubsectionRef &RVAs,
- const DebugSubsectionState &State) override {
- if (!opts::checkModuleSubsection(opts::ModuleSubsection::CoffSymbolRVAs))
- return Error::success();
-
- ListScope D(P, "COFF Symbol RVAs");
- P.printHexList("RVAs", RVAs);
- return Error::success();
- }
-
-private:
- Error dumpTypeRecord(StringRef Label, TypeIndex Index) {
- CompactTypeDumpVisitor CTDV(IPI, Index, &P);
- DictScope D(P, Label);
- if (IPI.contains(Index)) {
- CVType Type = IPI.getType(Index);
- if (auto EC = codeview::visitTypeRecord(Type, CTDV))
- return EC;
- } else {
- P.printString(
- llvm::formatv("Index: {0:x} (unknown function)", Index.getIndex())
- .str());
- }
- return Error::success();
- }
- Error printFileName(StringRef Label, uint32_t Offset,
- const DebugSubsectionState &State) {
- if (auto Result = getNameFromChecksumsBuffer(Offset, State)) {
- P.printString(Label, *Result);
- return Error::success();
- } else
- return Result.takeError();
- }
-
- Expected<StringRef>
- getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) {
- return State.strings().getString(Offset);
- }
-
- Expected<StringRef>
- getNameFromChecksumsBuffer(uint32_t Offset,
- const DebugSubsectionState &State) {
- auto Array = State.checksums().getArray();
- auto ChecksumIter = Array.at(Offset);
- if (ChecksumIter == Array.end())
- return make_error<RawError>(raw_error_code::invalid_format);
- const auto &Entry = *ChecksumIter;
- return getNameFromStringTable(Entry.FileNameOffset, State);
- }
-
- ScopedPrinter &P;
- LazyRandomTypeCollection &TPI;
- LazyRandomTypeCollection &IPI;
-};
-}
-
-static void recordKnownUsedPage(PageStats &Stats, uint32_t UsedIndex) {
- if (Stats.Upm.test(UsedIndex)) {
- if (Stats.ActualUsedPages.test(UsedIndex))
- Stats.MultiUsePages.set(UsedIndex);
- Stats.ActualUsedPages.set(UsedIndex);
- Stats.OrphanedPages.reset(UsedIndex);
- } else {
- // The MSF doesn't think this page is used, but it is.
- Stats.UseAfterFreePages.set(UsedIndex);
- }
-}
-
-static void printSectionOffset(llvm::raw_ostream &OS,
- const SectionOffset &Off) {
- OS << Off.Off << ", " << Off.Isect;
-}
-
-LLVMOutputStyle::LLVMOutputStyle(PDBFile &File) : File(File), P(outs()) {}
-
-Error LLVMOutputStyle::dump() {
- if (auto EC = dumpFileHeaders())
- return EC;
-
- if (auto EC = dumpStreamSummary())
- return EC;
-
- if (auto EC = dumpFreePageMap())
- return EC;
-
- if (auto EC = dumpStreamBlocks())
- return EC;
-
- if (auto EC = dumpBlockRanges())
- return EC;
-
- if (auto EC = dumpStreamBytes())
- return EC;
-
- if (auto EC = dumpStringTable())
- return EC;
-
- if (auto EC = dumpInfoStream())
- return EC;
-
- if (auto EC = dumpTpiStream(StreamTPI))
- return EC;
-
- if (auto EC = dumpTpiStream(StreamIPI))
- return EC;
-
- if (auto EC = dumpDbiStream())
- return EC;
-
- if (auto EC = dumpSectionContribs())
- return EC;
-
- if (auto EC = dumpSectionMap())
- return EC;
-
- if (auto EC = dumpGlobalsStream())
- return EC;
-
- if (auto EC = dumpPublicsStream())
- return EC;
-
- if (auto EC = dumpSectionHeaders())
- return EC;
-
- if (auto EC = dumpFpoStream())
- return EC;
-
- flush();
-
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpFileHeaders() {
- if (!opts::raw::DumpHeaders)
- return Error::success();
-
- DictScope D(P, "FileHeaders");
- P.printNumber("BlockSize", File.getBlockSize());
- P.printNumber("FreeBlockMap", File.getFreeBlockMapBlock());
- P.printNumber("NumBlocks", File.getBlockCount());
- P.printNumber("NumDirectoryBytes", File.getNumDirectoryBytes());
- P.printNumber("Unknown1", File.getUnknown1());
- P.printNumber("BlockMapAddr", File.getBlockMapIndex());
- P.printNumber("NumDirectoryBlocks", File.getNumDirectoryBlocks());
-
- // The directory is not contiguous. Instead, the block map contains a
- // contiguous list of block numbers whose contents, when concatenated in
- // order, make up the directory.
- P.printList("DirectoryBlocks", File.getDirectoryBlockArray());
- P.printNumber("NumStreams", File.getNumStreams());
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpStreamSummary() {
- if (!opts::raw::DumpStreamSummary)
- return Error::success();
-
- if (StreamPurposes.empty())
- discoverStreamPurposes(File, StreamPurposes);
-
- uint32_t StreamCount = File.getNumStreams();
-
- ListScope L(P, "Streams");
- for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
- std::string Label("Stream ");
- Label += to_string(StreamIdx);
-
- std::string Value = "[" + StreamPurposes[StreamIdx] + "] (";
- Value += to_string(File.getStreamByteSize(StreamIdx));
- Value += " bytes)";
-
- P.printString(Label, Value);
- }
-
- P.flush();
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpFreePageMap() {
- if (!opts::raw::DumpPageStats)
- return Error::success();
-
- // Start with used pages instead of free pages because
- // the number of free pages is far larger than used pages.
- BitVector FPM = File.getMsfLayout().FreePageMap;
-
- PageStats PS(FPM);
-
- recordKnownUsedPage(PS, 0); // MSF Super Block
-
- uint32_t BlocksPerSection = msf::getFpmIntervalLength(File.getMsfLayout());
- uint32_t NumSections = msf::getNumFpmIntervals(File.getMsfLayout());
- for (uint32_t I = 0; I < NumSections; ++I) {
- uint32_t Fpm0 = 1 + BlocksPerSection * I;
- // 2 Fpm blocks spaced at `getBlockSize()` block intervals
- recordKnownUsedPage(PS, Fpm0);
- recordKnownUsedPage(PS, Fpm0 + 1);
- }
-
- recordKnownUsedPage(PS, File.getBlockMapIndex()); // Stream Table
-
- for (auto DB : File.getDirectoryBlockArray())
- recordKnownUsedPage(PS, DB);
-
- // Record pages used by streams. Note that pages for stream 0
- // are considered being unused because that's what MSVC tools do.
- // Stream 0 doesn't contain actual data, so it makes some sense,
- // though it's a bit confusing to us.
- for (auto &SE : File.getStreamMap().drop_front(1))
- for (auto &S : SE)
- recordKnownUsedPage(PS, S);
-
- dumpBitVector("Msf Free Pages", FPM);
- dumpBitVector("Orphaned Pages", PS.OrphanedPages);
- dumpBitVector("Multiply Used Pages", PS.MultiUsePages);
- dumpBitVector("Use After Free Pages", PS.UseAfterFreePages);
- return Error::success();
-}
-
-void LLVMOutputStyle::dumpBitVector(StringRef Name, const BitVector &V) {
- std::vector<uint32_t> Vec;
- for (uint32_t I = 0, E = V.size(); I != E; ++I)
- if (V[I])
- Vec.push_back(I);
- P.printList(Name, Vec);
-}
-
-Error LLVMOutputStyle::dumpGlobalsStream() {
- if (!opts::raw::DumpGlobals)
- return Error::success();
- if (!File.hasPDBGlobalsStream()) {
- P.printString("Globals Stream not present");
- return Error::success();
- }
-
- auto Globals = File.getPDBGlobalsStream();
- if (!Globals)
- return Globals.takeError();
- DictScope D(P, "Globals Stream");
-
- auto Dbi = File.getPDBDbiStream();
- if (!Dbi)
- return Dbi.takeError();
-
- P.printNumber("Stream number", Dbi->getGlobalSymbolStreamIndex());
- P.printNumber("Number of buckets", Globals->getNumBuckets());
- P.printList("Hash Buckets", Globals->getHashBuckets());
-
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpStreamBlocks() {
- if (!opts::raw::DumpStreamBlocks)
- return Error::success();
-
- ListScope L(P, "StreamBlocks");
- uint32_t StreamCount = File.getNumStreams();
- for (uint32_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
- std::string Name("Stream ");
- Name += to_string(StreamIdx);
- auto StreamBlocks = File.getStreamBlockList(StreamIdx);
- P.printList(Name, StreamBlocks);
- }
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpBlockRanges() {
- if (!opts::raw::DumpBlockRange.hasValue())
- return Error::success();
- auto &R = *opts::raw::DumpBlockRange;
- uint32_t Max = R.Max.getValueOr(R.Min);
-
- if (Max < R.Min)
- return make_error<StringError>(
- "Invalid block range specified. Max < Min",
- std::make_error_code(std::errc::bad_address));
- if (Max >= File.getBlockCount())
- return make_error<StringError>(
- "Invalid block range specified. Requested block out of bounds",
- std::make_error_code(std::errc::bad_address));
-
- DictScope D(P, "Block Data");
- for (uint32_t I = R.Min; I <= Max; ++I) {
- auto ExpectedData = File.getBlockData(I, File.getBlockSize());
- if (!ExpectedData)
- return ExpectedData.takeError();
- std::string Label;
- llvm::raw_string_ostream S(Label);
- S << "Block " << I;
- S.flush();
- P.printBinaryBlock(Label, *ExpectedData);
- }
-
- return Error::success();
-}
-
-static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset,
- uint32_t &Size) {
- if (Str.consumeInteger(0, SI))
- return make_error<RawError>(raw_error_code::invalid_format,
- "Invalid Stream Specification");
- if (Str.consume_front(":")) {
- if (Str.consumeInteger(0, Offset))
- return make_error<RawError>(raw_error_code::invalid_format,
- "Invalid Stream Specification");
- }
- if (Str.consume_front("@")) {
- if (Str.consumeInteger(0, Size))
- return make_error<RawError>(raw_error_code::invalid_format,
- "Invalid Stream Specification");
- }
- if (!Str.empty())
- return make_error<RawError>(raw_error_code::invalid_format,
- "Invalid Stream Specification");
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpStreamBytes() {
- if (opts::raw::DumpStreamData.empty())
- return Error::success();
-
- if (StreamPurposes.empty())
- discoverStreamPurposes(File, StreamPurposes);
-
- DictScope D(P, "Stream Data");
- for (auto &Str : opts::raw::DumpStreamData) {
- uint32_t SI = 0;
- uint32_t Begin = 0;
- uint32_t Size = 0;
- uint32_t End = 0;
-
- if (auto EC = parseStreamSpec(Str, SI, Begin, Size))
- return EC;
-
- if (SI >= File.getNumStreams())
- return make_error<RawError>(raw_error_code::no_stream);
-
- auto S = MappedBlockStream::createIndexedStream(
- File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator());
- if (!S)
- continue;
- DictScope DD(P, "Stream");
- if (Size == 0)
- End = S->getLength();
- else {
- End = Begin + Size;
- if (End >= S->getLength())
- return make_error<RawError>(raw_error_code::index_out_of_bounds,
- "Stream is not long enough!");
- }
-
- P.printNumber("Index", SI);
- P.printString("Type", StreamPurposes[SI]);
- P.printNumber("Size", S->getLength());
- auto Blocks = File.getMsfLayout().StreamMap[SI];
- P.printList("Blocks", Blocks);
-
- BinaryStreamReader R(*S);
- ArrayRef<uint8_t> StreamData;
- if (auto EC = R.readBytes(StreamData, S->getLength()))
- return EC;
- Size = End - Begin;
- StreamData = StreamData.slice(Begin, Size);
- P.printBinaryBlock("Data", StreamData, Begin);
- }
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpStringTable() {
- if (!opts::raw::DumpStringTable)
- return Error::success();
-
- auto IS = File.getStringTable();
- if (!IS)
- return IS.takeError();
-
- DictScope D(P, "String Table");
- for (uint32_t I : IS->name_ids()) {
- auto ES = IS->getStringForID(I);
- if (!ES)
- return ES.takeError();
-
- if (ES->empty())
- continue;
- llvm::SmallString<32> Str;
- Str.append("'");
- Str.append(*ES);
- Str.append("'");
- P.printString(Str);
- }
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpInfoStream() {
- if (!opts::raw::DumpHeaders)
- return Error::success();
- if (!File.hasPDBInfoStream()) {
- P.printString("PDB Stream not present");
- return Error::success();
- }
- auto IS = File.getPDBInfoStream();
- if (!IS)
- return IS.takeError();
-
- DictScope D(P, "PDB Stream");
- P.printNumber("Version", IS->getVersion());
- P.printHex("Signature", IS->getSignature());
- P.printNumber("Age", IS->getAge());
- P.printObject("Guid", IS->getGuid());
- P.printHex("Features", IS->getFeatures());
- {
- DictScope DD(P, "Named Streams");
- for (const auto &S : IS->getNamedStreams().entries())
- P.printObject(S.getKey(), S.getValue());
- }
- return Error::success();
-}
-
-namespace {
-class RecordBytesVisitor : public TypeVisitorCallbacks {
-public:
- explicit RecordBytesVisitor(ScopedPrinter &P) : P(P) {}
-
- Error visitTypeEnd(CVType &Record) override {
- P.printBinaryBlock("Bytes", Record.content());
- return Error::success();
- }
-
-private:
- ScopedPrinter &P;
-};
-}
-
-Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
- assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
-
- bool DumpRecordBytes = false;
- bool DumpRecords = false;
- bool DumpTpiHash = false;
- StringRef Label;
- StringRef VerLabel;
- if (StreamIdx == StreamTPI) {
- if (!File.hasPDBTpiStream()) {
- P.printString("Type Info Stream (TPI) not present");
- return Error::success();
- }
- DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
- DumpRecords = opts::raw::DumpTpiRecords;
- DumpTpiHash = opts::raw::DumpTpiHash;
- Label = "Type Info Stream (TPI)";
- VerLabel = "TPI Version";
- } else if (StreamIdx == StreamIPI) {
- if (!File.hasPDBIpiStream()) {
- P.printString("Type Info Stream (IPI) not present");
- return Error::success();
- }
- DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
- DumpRecords = opts::raw::DumpIpiRecords;
- Label = "Type Info Stream (IPI)";
- VerLabel = "IPI Version";
- }
-
- auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
- : File.getPDBIpiStream();
- if (!Tpi)
- return Tpi.takeError();
-
- auto ExpectedTypes = initializeTypeDatabase(StreamIdx);
- if (!ExpectedTypes)
- return ExpectedTypes.takeError();
- auto &Types = *ExpectedTypes;
-
- if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash)
- return Error::success();
-
- std::unique_ptr<DictScope> StreamScope;
- std::unique_ptr<ListScope> RecordScope;
-
- StreamScope = llvm::make_unique<DictScope>(P, Label);
- P.printNumber(VerLabel, Tpi->getTpiVersion());
- P.printNumber("Record count", Tpi->getNumTypeRecords());
-
- std::vector<std::unique_ptr<TypeVisitorCallbacks>> Visitors;
-
- // If we're in dump mode, add a dumper with the appropriate detail level.
- if (DumpRecords) {
- std::unique_ptr<TypeVisitorCallbacks> Dumper;
- if (opts::raw::CompactRecords)
- Dumper = make_unique<CompactTypeDumpVisitor>(Types, &P);
- else {
- assert(TpiTypes);
-
- auto X = make_unique<TypeDumpVisitor>(*TpiTypes, &P, false);
- if (StreamIdx == StreamIPI)
- X->setIpiTypes(*IpiTypes);
- Dumper = std::move(X);
- }
- Visitors.push_back(std::move(Dumper));
- }
- if (DumpRecordBytes)
- Visitors.push_back(make_unique<RecordBytesVisitor>(P));
-
- // We always need to deserialize and add it to the type database. This is
- // true if even if we're not dumping anything, because we could need the
- // type database for the purposes of dumping symbols.
- TypeVisitorCallbackPipeline Pipeline;
- for (const auto &V : Visitors)
- Pipeline.addCallbackToPipeline(*V);
-
- if (DumpRecords || DumpRecordBytes)
- RecordScope = llvm::make_unique<ListScope>(P, "Records");
-
- Optional<TypeIndex> I = Types.getFirst();
- while (I) {
- std::unique_ptr<DictScope> OneRecordScope;
-
- if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords)
- OneRecordScope = llvm::make_unique<DictScope>(P, "");
-
- auto T = Types.getType(*I);
- if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline))
- return EC;
- I = Types.getNext(*I);
- }
-
- if (DumpTpiHash) {
- DictScope DD(P, "Hash");
- P.printNumber("Number of Hash Buckets", Tpi->getNumHashBuckets());
- P.printNumber("Hash Key Size", Tpi->getHashKeySize());
- P.printList("Values", Tpi->getHashValues());
-
- ListScope LHA(P, "Adjusters");
- auto ExpectedST = File.getStringTable();
- if (!ExpectedST)
- return ExpectedST.takeError();
- const auto &ST = *ExpectedST;
- for (const auto &E : Tpi->getHashAdjusters()) {
- DictScope DHA(P);
- auto Name = ST.getStringForID(E.first);
- if (!Name)
- return Name.takeError();
-
- P.printString("Type", *Name);
- P.printHex("TI", E.second);
- }
- }
-
- ListScope L(P, "TypeIndexOffsets");
- for (const auto &IO : Tpi->getTypeIndexOffsets()) {
- P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(),
- (uint32_t)IO.Offset)
- .str());
- }
-
- P.flush();
- return Error::success();
-}
-
-Expected<codeview::LazyRandomTypeCollection &>
-LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) {
- auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
- auto Tpi =
- (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
- if (!Tpi)
- return Tpi.takeError();
-
- if (!TypeCollection) {
- // Initialize the type collection, even if we're not going to dump it. This
- // way if some other part of the dumper decides it wants to use some or all
- // of the records for whatever purposes, it can still access them lazily.
- auto &Types = Tpi->typeArray();
- uint32_t Count = Tpi->getNumTypeRecords();
- auto Offsets = Tpi->getTypeIndexOffsets();
- TypeCollection =
- llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
- }
-
- return *TypeCollection;
-}
-
-Error LLVMOutputStyle::dumpDbiStream() {
- bool DumpModules = opts::shared::DumpModules ||
- opts::shared::DumpModuleSyms ||
- opts::shared::DumpModuleFiles ||
- !opts::shared::DumpModuleSubsections.empty();
- if (!opts::raw::DumpHeaders && !DumpModules)
- return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
-
- auto DS = File.getPDBDbiStream();
- if (!DS)
- return DS.takeError();
-
- DictScope D(P, "DBI Stream");
- P.printNumber("Dbi Version", DS->getDbiVersion());
- P.printNumber("Age", DS->getAge());
- P.printBoolean("Incremental Linking", DS->isIncrementallyLinked());
- P.printBoolean("Has CTypes", DS->hasCTypes());
- P.printBoolean("Is Stripped", DS->isStripped());
- P.printObject("Machine Type", DS->getMachineType());
- P.printNumber("Symbol Record Stream Index", DS->getSymRecordStreamIndex());
- P.printNumber("Public Symbol Stream Index", DS->getPublicSymbolStreamIndex());
- P.printNumber("Global Symbol Stream Index", DS->getGlobalSymbolStreamIndex());
-
- uint16_t Major = DS->getBuildMajorVersion();
- uint16_t Minor = DS->getBuildMinorVersion();
- P.printVersion("Toolchain Version", Major, Minor);
-
- std::string DllName;
- raw_string_ostream DllStream(DllName);
- DllStream << "mspdb" << Major << Minor << ".dll version";
- DllStream.flush();
- P.printVersion(DllName, Major, Minor, DS->getPdbDllVersion());
-
- if (DumpModules) {
- ListScope L(P, "Modules");
- const DbiModuleList &Modules = DS->modules();
- for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
- const DbiModuleDescriptor &Modi = Modules.getModuleDescriptor(I);
- DictScope DD(P);
- P.printString("Name", Modi.getModuleName().str());
- P.printNumber("Debug Stream Index", Modi.getModuleStreamIndex());
- P.printString("Object File Name", Modi.getObjFileName().str());
- P.printNumber("Num Files", Modi.getNumberOfFiles());
- P.printNumber("Source File Name Idx", Modi.getSourceFileNameIndex());
- P.printNumber("Pdb File Name Idx", Modi.getPdbFilePathNameIndex());
- P.printNumber("Line Info Byte Size", Modi.getC11LineInfoByteSize());
- P.printNumber("C13 Line Info Byte Size", Modi.getC13LineInfoByteSize());
- P.printNumber("Symbol Byte Size", Modi.getSymbolDebugInfoByteSize());
- P.printNumber("Type Server Index", Modi.getTypeServerIndex());
- P.printBoolean("Has EC Info", Modi.hasECInfo());
- if (opts::shared::DumpModuleFiles) {
- std::string FileListName = to_string(Modules.getSourceFileCount(I)) +
- " Contributing Source Files";
- ListScope LL(P, FileListName);
- for (auto File : Modules.source_files(I))
- P.printString(File);
- }
- bool HasModuleDI = (Modi.getModuleStreamIndex() < File.getNumStreams());
- bool ShouldDumpSymbols =
- (opts::shared::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
- if (HasModuleDI &&
- (ShouldDumpSymbols || !opts::shared::DumpModuleSubsections.empty())) {
- auto ModStreamData = MappedBlockStream::createIndexedStream(
- File.getMsfLayout(), File.getMsfBuffer(),
- Modi.getModuleStreamIndex(), File.getAllocator());
-
- ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
- if (auto EC = ModS.reload())
- return EC;
-
- auto ExpectedTpi = initializeTypeDatabase(StreamTPI);
- if (!ExpectedTpi)
- return ExpectedTpi.takeError();
- auto &Tpi = *ExpectedTpi;
- if (ShouldDumpSymbols) {
-
- ListScope SS(P, "Symbols");
- codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr,
- false);
- bool HadError = false;
- for (auto S : ModS.symbols(&HadError)) {
- DictScope LL(P, "");
- if (opts::shared::DumpModuleSyms) {
- if (auto EC = SD.dump(S)) {
- llvm::consumeError(std::move(EC));
- HadError = true;
- break;
- }
- }
- if (opts::raw::DumpSymRecordBytes)
- P.printBinaryBlock("Bytes", S.content());
- }
- if (HadError)
- return make_error<RawError>(
- raw_error_code::corrupt_file,
- "DBI stream contained corrupt symbol record");
- }
- if (!opts::shared::DumpModuleSubsections.empty()) {
- ListScope SS(P, "Subsections");
- auto ExpectedIpi = initializeTypeDatabase(StreamIPI);
- if (!ExpectedIpi)
- return ExpectedIpi.takeError();
- auto &Ipi = *ExpectedIpi;
- auto ExpectedStrings = File.getStringTable();
- if (!ExpectedStrings)
- return joinErrors(
- make_error<RawError>(raw_error_code::no_stream,
- "Could not get string table!"),
- ExpectedStrings.takeError());
-
- C13RawVisitor V(P, Tpi, Ipi);
- if (auto EC = codeview::visitDebugSubsections(
- ModS.subsections(), V, ExpectedStrings->getStringTable()))
- return EC;
- }
- }
- }
- }
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpSectionContribs() {
- if (!opts::raw::DumpSectionContribs)
- return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
-
- auto Dbi = File.getPDBDbiStream();
- if (!Dbi)
- return Dbi.takeError();
-
- ListScope L(P, "Section Contributions");
- class Visitor : public ISectionContribVisitor {
- public:
- Visitor(ScopedPrinter &P, DbiStream &DS) : P(P), DS(DS) {}
- void visit(const SectionContrib &SC) override {
- DictScope D(P, "Contribution");
- P.printNumber("ISect", SC.ISect);
- P.printNumber("Off", SC.Off);
- P.printNumber("Size", SC.Size);
- P.printFlags("Characteristics", SC.Characteristics,
- codeview::getImageSectionCharacteristicNames(),
- COFF::SectionCharacteristics(0x00F00000));
- {
- DictScope DD(P, "Module");
- P.printNumber("Index", SC.Imod);
- const DbiModuleList &Modules = DS.modules();
- if (Modules.getModuleCount() > SC.Imod) {
- P.printString("Name",
- Modules.getModuleDescriptor(SC.Imod).getModuleName());
- }
- }
- P.printNumber("Data CRC", SC.DataCrc);
- P.printNumber("Reloc CRC", SC.RelocCrc);
- P.flush();
- }
- void visit(const SectionContrib2 &SC) override {
- visit(SC.Base);
- P.printNumber("ISect Coff", SC.ISectCoff);
- P.flush();
- }
-
- private:
- ScopedPrinter &P;
- DbiStream &DS;
- };
- Visitor V(P, *Dbi);
- Dbi->visitSectionContributions(V);
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpSectionMap() {
- if (!opts::raw::DumpSectionMap)
- return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
-
- auto Dbi = File.getPDBDbiStream();
- if (!Dbi)
- return Dbi.takeError();
-
- ListScope L(P, "Section Map");
- for (auto &M : Dbi->getSectionMap()) {
- DictScope D(P, "Entry");
- P.printFlags("Flags", M.Flags, getOMFSegMapDescFlagNames());
- P.printNumber("Ovl", M.Ovl);
- P.printNumber("Group", M.Group);
- P.printNumber("Frame", M.Frame);
- P.printNumber("SecName", M.SecName);
- P.printNumber("ClassName", M.ClassName);
- P.printNumber("Offset", M.Offset);
- P.printNumber("SecByteLength", M.SecByteLength);
- P.flush();
- }
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpPublicsStream() {
- if (!opts::raw::DumpPublics)
- return Error::success();
- if (!File.hasPDBPublicsStream()) {
- P.printString("Publics Stream not present");
- return Error::success();
- }
-
- auto Publics = File.getPDBPublicsStream();
- if (!Publics)
- return Publics.takeError();
- DictScope D(P, "Publics Stream");
-
- auto Dbi = File.getPDBDbiStream();
- if (!Dbi)
- return Dbi.takeError();
-
- P.printNumber("Stream number", Dbi->getPublicSymbolStreamIndex());
- P.printNumber("SymHash", Publics->getSymHash());
- P.printNumber("AddrMap", Publics->getAddrMap());
- P.printNumber("Number of buckets", Publics->getNumBuckets());
- P.printList("Hash Buckets", Publics->getHashBuckets());
- P.printList("Address Map", Publics->getAddressMap());
- P.printList("Thunk Map", Publics->getThunkMap());
- P.printList("Section Offsets", Publics->getSectionOffsets(),
- printSectionOffset);
- ListScope L(P, "Symbols");
- auto ExpectedTypes = initializeTypeDatabase(StreamTPI);
- if (!ExpectedTypes)
- return ExpectedTypes.takeError();
- auto &Tpi = *ExpectedTypes;
-
- codeview::CVSymbolDumper SD(P, Tpi, CodeViewContainer::Pdb, nullptr, false);
- bool HadError = false;
- for (auto S : Publics->getSymbols(&HadError)) {
- DictScope DD(P, "");
-
- if (auto EC = SD.dump(S)) {
- HadError = true;
- break;
- }
- if (opts::raw::DumpSymRecordBytes)
- P.printBinaryBlock("Bytes", S.content());
- }
- if (HadError)
- return make_error<RawError>(
- raw_error_code::corrupt_file,
- "Public symbol stream contained corrupt record");
-
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpSectionHeaders() {
- if (!opts::raw::DumpSectionHeaders)
- return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
-
- auto Dbi = File.getPDBDbiStream();
- if (!Dbi)
- return Dbi.takeError();
-
- ListScope D(P, "Section Headers");
- for (const object::coff_section &Section : Dbi->getSectionHeaders()) {
- DictScope DD(P, "");
-
- // If a name is 8 characters long, there is no NUL character at end.
- StringRef Name(Section.Name, strnlen(Section.Name, sizeof(Section.Name)));
- P.printString("Name", Name);
- P.printNumber("Virtual Size", Section.VirtualSize);
- P.printNumber("Virtual Address", Section.VirtualAddress);
- P.printNumber("Size of Raw Data", Section.SizeOfRawData);
- P.printNumber("File Pointer to Raw Data", Section.PointerToRawData);
- P.printNumber("File Pointer to Relocations", Section.PointerToRelocations);
- P.printNumber("File Pointer to Linenumbers", Section.PointerToLinenumbers);
- P.printNumber("Number of Relocations", Section.NumberOfRelocations);
- P.printNumber("Number of Linenumbers", Section.NumberOfLinenumbers);
- P.printFlags("Characteristics", Section.Characteristics,
- getImageSectionCharacteristicNames());
- }
- return Error::success();
-}
-
-Error LLVMOutputStyle::dumpFpoStream() {
- if (!opts::raw::DumpFpo)
- return Error::success();
- if (!File.hasPDBDbiStream()) {
- P.printString("DBI Stream not present");
- return Error::success();
- }
-
- auto Dbi = File.getPDBDbiStream();
- if (!Dbi)
- return Dbi.takeError();
-
- ListScope D(P, "New FPO");
- for (const object::FpoData &Fpo : Dbi->getFpoRecords()) {
- DictScope DD(P, "");
- P.printNumber("Offset", Fpo.Offset);
- P.printNumber("Size", Fpo.Size);
- P.printNumber("Number of locals", Fpo.NumLocals);
- P.printNumber("Number of params", Fpo.NumParams);
- P.printNumber("Size of Prolog", Fpo.getPrologSize());
- P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs());
- P.printBoolean("Has SEH", Fpo.hasSEH());
- P.printBoolean("Use BP", Fpo.useBP());
- P.printNumber("Frame Pointer", Fpo.getFP());
- }
- return Error::success();
-}
-
-void LLVMOutputStyle::flush() { P.flush(); }
diff --git a/tools/llvm-pdbutil/LinePrinter.cpp b/tools/llvm-pdbutil/LinePrinter.cpp
index ef56b5fe8e6a..718d3394e211 100644
--- a/tools/llvm-pdbutil/LinePrinter.cpp
+++ b/tools/llvm-pdbutil/LinePrinter.cpp
@@ -13,6 +13,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/PDB/UDTLayout.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/Regex.h"
#include <algorithm>
@@ -60,10 +61,16 @@ LinePrinter::LinePrinter(int Indent, bool UseColor, llvm::raw_ostream &Stream)
opts::pretty::IncludeCompilands.end());
}
-void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
+void LinePrinter::Indent(uint32_t Amount) {
+ if (Amount == 0)
+ Amount = IndentSpaces;
+ CurrentIndent += Amount;
+}
-void LinePrinter::Unindent() {
- CurrentIndent = std::max(0, CurrentIndent - IndentSpaces);
+void LinePrinter::Unindent(uint32_t Amount) {
+ if (Amount == 0)
+ Amount = IndentSpaces;
+ CurrentIndent = std::max<int>(0, CurrentIndent - Amount);
}
void LinePrinter::NewLine() {
@@ -71,6 +78,13 @@ void LinePrinter::NewLine() {
OS.indent(CurrentIndent);
}
+void LinePrinter::print(const Twine &T) { OS << T; }
+
+void LinePrinter::printLine(const Twine &T) {
+ NewLine();
+ OS << T;
+}
+
bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
if (IsTypeExcluded(Class.getName(), Class.getSize()))
return true;
@@ -79,6 +93,19 @@ bool LinePrinter::IsClassExcluded(const ClassLayout &Class) {
return false;
}
+void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
+ uint32_t StartOffset) {
+ NewLine();
+ OS << Label << " (";
+ if (!Data.empty()) {
+ OS << "\n";
+ OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,
+ CurrentIndent + IndentSpaces, true);
+ NewLine();
+ }
+ OS << ")";
+}
+
bool LinePrinter::IsTypeExcluded(llvm::StringRef TypeName, uint32_t Size) {
if (IsItemExcluded(TypeName, IncludeTypeFilters, ExcludeTypeFilters))
return true;
diff --git a/tools/llvm-pdbutil/LinePrinter.h b/tools/llvm-pdbutil/LinePrinter.h
index 1a922feb1e62..f4fd22bcb6f4 100644
--- a/tools/llvm-pdbutil/LinePrinter.h
+++ b/tools/llvm-pdbutil/LinePrinter.h
@@ -10,10 +10,12 @@
#ifndef LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
#define LLVM_TOOLS_LLVMPDBDUMP_LINEPRINTER_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Regex.h"
+#include "llvm/Support/raw_ostream.h"
#include <list>
@@ -28,10 +30,22 @@ class LinePrinter {
public:
LinePrinter(int Indent, bool UseColor, raw_ostream &Stream);
- void Indent();
- void Unindent();
+ void Indent(uint32_t Amount = 0);
+ void Unindent(uint32_t Amount = 0);
void NewLine();
+ void printLine(const Twine &T);
+ void print(const Twine &T);
+ template <typename... Ts> void formatLine(const char *Fmt, Ts &&... Items) {
+ printLine(formatv(Fmt, std::forward<Ts>(Items)...));
+ }
+ template <typename... Ts> void format(const char *Fmt, Ts &&... Items) {
+ print(formatv(Fmt, std::forward<Ts>(Items)...));
+ }
+
+ void formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
+ uint32_t StartOffset);
+
bool hasColor() const { return UseColor; }
raw_ostream &getStream() { return OS; }
int getIndentLevel() const { return CurrentIndent; }
@@ -63,6 +77,17 @@ private:
std::list<Regex> IncludeSymbolFilters;
};
+struct AutoIndent {
+ explicit AutoIndent(LinePrinter &L, uint32_t Amount = 0)
+ : L(L), Amount(Amount) {
+ L.Indent(Amount);
+ }
+ ~AutoIndent() { L.Unindent(Amount); }
+
+ LinePrinter &L;
+ uint32_t Amount = 0;
+};
+
template <class T>
inline raw_ostream &operator<<(LinePrinter &Printer, const T &Item) {
Printer.getStream() << Item;
diff --git a/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
new file mode 100644
index 000000000000..8b36de0b7157
--- /dev/null
+++ b/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
@@ -0,0 +1,749 @@
+//===- MinimalSymbolDumper.cpp -------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MinimalSymbolDumper.h"
+
+#include "FormatUtil.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/FormatVariadic.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static StringRef getSymbolKindName(SymbolKind K) {
+ switch (K) {
+#define SYMBOL_RECORD(EnumName, value, name) \
+ case EnumName: \
+ return #EnumName;
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+ default:
+ llvm_unreachable("Unknown symbol kind!");
+ }
+ return "";
+}
+
+static std::string formatLocalSymFlags(uint32_t IndentLevel,
+ LocalSymFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == LocalSymFlags::None)
+ return "none";
+
+ PUSH_FLAG(LocalSymFlags, IsParameter, Flags, "param");
+ PUSH_FLAG(LocalSymFlags, IsAddressTaken, Flags, "address is taken");
+ PUSH_FLAG(LocalSymFlags, IsCompilerGenerated, Flags, "compiler generated");
+ PUSH_FLAG(LocalSymFlags, IsAggregate, Flags, "aggregate");
+ PUSH_FLAG(LocalSymFlags, IsAggregated, Flags, "aggregated");
+ PUSH_FLAG(LocalSymFlags, IsAliased, Flags, "aliased");
+ PUSH_FLAG(LocalSymFlags, IsAlias, Flags, "alias");
+ PUSH_FLAG(LocalSymFlags, IsReturnValue, Flags, "return val");
+ PUSH_FLAG(LocalSymFlags, IsOptimizedOut, Flags, "optimized away");
+ PUSH_FLAG(LocalSymFlags, IsEnregisteredGlobal, Flags, "enreg global");
+ PUSH_FLAG(LocalSymFlags, IsEnregisteredStatic, Flags, "enreg static");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatExportFlags(uint32_t IndentLevel, ExportFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == ExportFlags::None)
+ return "none";
+
+ PUSH_FLAG(ExportFlags, IsConstant, Flags, "constant");
+ PUSH_FLAG(ExportFlags, IsData, Flags, "data");
+ PUSH_FLAG(ExportFlags, IsPrivate, Flags, "private");
+ PUSH_FLAG(ExportFlags, HasNoName, Flags, "no name");
+ PUSH_FLAG(ExportFlags, HasExplicitOrdinal, Flags, "explicit ord");
+ PUSH_FLAG(ExportFlags, IsForwarder, Flags, "forwarder");
+
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatCompileSym2Flags(uint32_t IndentLevel,
+ CompileSym2Flags Flags) {
+ std::vector<std::string> Opts;
+ Flags &= ~CompileSym2Flags::SourceLanguageMask;
+ if (Flags == CompileSym2Flags::None)
+ return "none";
+
+ PUSH_FLAG(CompileSym2Flags, EC, Flags, "edit and continue");
+ PUSH_FLAG(CompileSym2Flags, NoDbgInfo, Flags, "no dbg info");
+ PUSH_FLAG(CompileSym2Flags, LTCG, Flags, "ltcg");
+ PUSH_FLAG(CompileSym2Flags, NoDataAlign, Flags, "no data align");
+ PUSH_FLAG(CompileSym2Flags, ManagedPresent, Flags, "has managed code");
+ PUSH_FLAG(CompileSym2Flags, SecurityChecks, Flags, "security checks");
+ PUSH_FLAG(CompileSym2Flags, HotPatch, Flags, "hot patchable");
+ PUSH_FLAG(CompileSym2Flags, CVTCIL, Flags, "cvtcil");
+ PUSH_FLAG(CompileSym2Flags, MSILModule, Flags, "msil module");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatCompileSym3Flags(uint32_t IndentLevel,
+ CompileSym3Flags Flags) {
+ std::vector<std::string> Opts;
+ Flags &= ~CompileSym3Flags::SourceLanguageMask;
+
+ if (Flags == CompileSym3Flags::None)
+ return "none";
+
+ PUSH_FLAG(CompileSym3Flags, EC, Flags, "edit and continue");
+ PUSH_FLAG(CompileSym3Flags, NoDbgInfo, Flags, "no dbg info");
+ PUSH_FLAG(CompileSym3Flags, LTCG, Flags, "ltcg");
+ PUSH_FLAG(CompileSym3Flags, NoDataAlign, Flags, "no data align");
+ PUSH_FLAG(CompileSym3Flags, ManagedPresent, Flags, "has managed code");
+ PUSH_FLAG(CompileSym3Flags, SecurityChecks, Flags, "security checks");
+ PUSH_FLAG(CompileSym3Flags, HotPatch, Flags, "hot patchable");
+ PUSH_FLAG(CompileSym3Flags, CVTCIL, Flags, "cvtcil");
+ PUSH_FLAG(CompileSym3Flags, MSILModule, Flags, "msil module");
+ PUSH_FLAG(CompileSym3Flags, Sdl, Flags, "sdl");
+ PUSH_FLAG(CompileSym3Flags, PGO, Flags, "pgo");
+ PUSH_FLAG(CompileSym3Flags, Exp, Flags, "exp");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatFrameProcedureOptions(uint32_t IndentLevel,
+ FrameProcedureOptions FPO) {
+ std::vector<std::string> Opts;
+ if (FPO == FrameProcedureOptions::None)
+ return "none";
+
+ PUSH_FLAG(FrameProcedureOptions, HasAlloca, FPO, "has alloca");
+ PUSH_FLAG(FrameProcedureOptions, HasSetJmp, FPO, "has setjmp");
+ PUSH_FLAG(FrameProcedureOptions, HasLongJmp, FPO, "has longjmp");
+ PUSH_FLAG(FrameProcedureOptions, HasInlineAssembly, FPO, "has inline asm");
+ PUSH_FLAG(FrameProcedureOptions, HasExceptionHandling, FPO, "has eh");
+ PUSH_FLAG(FrameProcedureOptions, MarkedInline, FPO, "marked inline");
+ PUSH_FLAG(FrameProcedureOptions, HasStructuredExceptionHandling, FPO,
+ "has seh");
+ PUSH_FLAG(FrameProcedureOptions, Naked, FPO, "naked");
+ PUSH_FLAG(FrameProcedureOptions, SecurityChecks, FPO, "secure checks");
+ PUSH_FLAG(FrameProcedureOptions, AsynchronousExceptionHandling, FPO,
+ "has async eh");
+ PUSH_FLAG(FrameProcedureOptions, NoStackOrderingForSecurityChecks, FPO,
+ "no stack order");
+ PUSH_FLAG(FrameProcedureOptions, Inlined, FPO, "inlined");
+ PUSH_FLAG(FrameProcedureOptions, StrictSecurityChecks, FPO,
+ "strict secure checks");
+ PUSH_FLAG(FrameProcedureOptions, SafeBuffers, FPO, "safe buffers");
+ PUSH_FLAG(FrameProcedureOptions, ProfileGuidedOptimization, FPO, "pgo");
+ PUSH_FLAG(FrameProcedureOptions, ValidProfileCounts, FPO,
+ "has profile counts");
+ PUSH_FLAG(FrameProcedureOptions, OptimizedForSpeed, FPO, "opt speed");
+ PUSH_FLAG(FrameProcedureOptions, GuardCfg, FPO, "guard cfg");
+ PUSH_FLAG(FrameProcedureOptions, GuardCfw, FPO, "guard cfw");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatProcSymFlags(uint32_t IndentLevel,
+ ProcSymFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == ProcSymFlags::None)
+ return "none";
+
+ PUSH_FLAG(ProcSymFlags, HasFP, Flags, "has fp");
+ PUSH_FLAG(ProcSymFlags, HasIRET, Flags, "has iret");
+ PUSH_FLAG(ProcSymFlags, HasFRET, Flags, "has fret");
+ PUSH_FLAG(ProcSymFlags, IsNoReturn, Flags, "noreturn");
+ PUSH_FLAG(ProcSymFlags, IsUnreachable, Flags, "unreachable");
+ PUSH_FLAG(ProcSymFlags, HasCustomCallingConv, Flags, "custom calling conv");
+ PUSH_FLAG(ProcSymFlags, IsNoInline, Flags, "noinline");
+ PUSH_FLAG(ProcSymFlags, HasOptimizedDebugInfo, Flags, "opt debuginfo");
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string formatThunkOrdinal(ThunkOrdinal Ordinal) {
+ switch (Ordinal) {
+ RETURN_CASE(ThunkOrdinal, Standard, "thunk");
+ RETURN_CASE(ThunkOrdinal, ThisAdjustor, "this adjustor");
+ RETURN_CASE(ThunkOrdinal, Vcall, "vcall");
+ RETURN_CASE(ThunkOrdinal, Pcode, "pcode");
+ RETURN_CASE(ThunkOrdinal, UnknownLoad, "unknown load");
+ RETURN_CASE(ThunkOrdinal, TrampIncremental, "tramp incremental");
+ RETURN_CASE(ThunkOrdinal, BranchIsland, "branch island");
+ }
+ return formatUnknownEnum(Ordinal);
+}
+
+static std::string formatTrampolineType(TrampolineType Tramp) {
+ switch (Tramp) {
+ RETURN_CASE(TrampolineType, TrampIncremental, "tramp incremental");
+ RETURN_CASE(TrampolineType, BranchIsland, "branch island");
+ }
+ return formatUnknownEnum(Tramp);
+}
+
+static std::string formatSourceLanguage(SourceLanguage Lang) {
+ switch (Lang) {
+ RETURN_CASE(SourceLanguage, C, "c");
+ RETURN_CASE(SourceLanguage, Cpp, "c++");
+ RETURN_CASE(SourceLanguage, Fortran, "fortran");
+ RETURN_CASE(SourceLanguage, Masm, "masm");
+ RETURN_CASE(SourceLanguage, Pascal, "pascal");
+ RETURN_CASE(SourceLanguage, Basic, "basic");
+ RETURN_CASE(SourceLanguage, Cobol, "cobol");
+ RETURN_CASE(SourceLanguage, Link, "link");
+ RETURN_CASE(SourceLanguage, VB, "vb");
+ RETURN_CASE(SourceLanguage, Cvtres, "cvtres");
+ RETURN_CASE(SourceLanguage, Cvtpgd, "cvtpgd");
+ RETURN_CASE(SourceLanguage, CSharp, "c#");
+ RETURN_CASE(SourceLanguage, ILAsm, "il asm");
+ RETURN_CASE(SourceLanguage, Java, "java");
+ RETURN_CASE(SourceLanguage, JScript, "javascript");
+ RETURN_CASE(SourceLanguage, MSIL, "msil");
+ RETURN_CASE(SourceLanguage, HLSL, "hlsl");
+ }
+ return formatUnknownEnum(Lang);
+}
+
+static std::string formatMachineType(CPUType Cpu) {
+ switch (Cpu) {
+ RETURN_CASE(CPUType, Intel8080, "intel 8080");
+ RETURN_CASE(CPUType, Intel8086, "intel 8086");
+ RETURN_CASE(CPUType, Intel80286, "intel 80286");
+ RETURN_CASE(CPUType, Intel80386, "intel 80386");
+ RETURN_CASE(CPUType, Intel80486, "intel 80486");
+ RETURN_CASE(CPUType, Pentium, "intel pentium");
+ RETURN_CASE(CPUType, PentiumPro, "intel pentium pro");
+ RETURN_CASE(CPUType, Pentium3, "intel pentium 3");
+ RETURN_CASE(CPUType, MIPS, "mips");
+ RETURN_CASE(CPUType, MIPS16, "mips-16");
+ RETURN_CASE(CPUType, MIPS32, "mips-32");
+ RETURN_CASE(CPUType, MIPS64, "mips-64");
+ RETURN_CASE(CPUType, MIPSI, "mips i");
+ RETURN_CASE(CPUType, MIPSII, "mips ii");
+ RETURN_CASE(CPUType, MIPSIII, "mips iii");
+ RETURN_CASE(CPUType, MIPSIV, "mips iv");
+ RETURN_CASE(CPUType, MIPSV, "mips v");
+ RETURN_CASE(CPUType, M68000, "motorola 68000");
+ RETURN_CASE(CPUType, M68010, "motorola 68010");
+ RETURN_CASE(CPUType, M68020, "motorola 68020");
+ RETURN_CASE(CPUType, M68030, "motorola 68030");
+ RETURN_CASE(CPUType, M68040, "motorola 68040");
+ RETURN_CASE(CPUType, Alpha, "alpha");
+ RETURN_CASE(CPUType, Alpha21164, "alpha 21164");
+ RETURN_CASE(CPUType, Alpha21164A, "alpha 21164a");
+ RETURN_CASE(CPUType, Alpha21264, "alpha 21264");
+ RETURN_CASE(CPUType, Alpha21364, "alpha 21364");
+ RETURN_CASE(CPUType, PPC601, "powerpc 601");
+ RETURN_CASE(CPUType, PPC603, "powerpc 603");
+ RETURN_CASE(CPUType, PPC604, "powerpc 604");
+ RETURN_CASE(CPUType, PPC620, "powerpc 620");
+ RETURN_CASE(CPUType, PPCFP, "powerpc fp");
+ RETURN_CASE(CPUType, PPCBE, "powerpc be");
+ RETURN_CASE(CPUType, SH3, "sh3");
+ RETURN_CASE(CPUType, SH3E, "sh3e");
+ RETURN_CASE(CPUType, SH3DSP, "sh3 dsp");
+ RETURN_CASE(CPUType, SH4, "sh4");
+ RETURN_CASE(CPUType, SHMedia, "shmedia");
+ RETURN_CASE(CPUType, ARM3, "arm 3");
+ RETURN_CASE(CPUType, ARM4, "arm 4");
+ RETURN_CASE(CPUType, ARM4T, "arm 4t");
+ RETURN_CASE(CPUType, ARM5, "arm 5");
+ RETURN_CASE(CPUType, ARM5T, "arm 5t");
+ RETURN_CASE(CPUType, ARM6, "arm 6");
+ RETURN_CASE(CPUType, ARM_XMAC, "arm xmac");
+ RETURN_CASE(CPUType, ARM_WMMX, "arm wmmx");
+ RETURN_CASE(CPUType, ARM7, "arm 7");
+ RETURN_CASE(CPUType, Omni, "omni");
+ RETURN_CASE(CPUType, Ia64, "intel itanium ia64");
+ RETURN_CASE(CPUType, Ia64_2, "intel itanium ia64 2");
+ RETURN_CASE(CPUType, CEE, "cee");
+ RETURN_CASE(CPUType, AM33, "am33");
+ RETURN_CASE(CPUType, M32R, "m32r");
+ RETURN_CASE(CPUType, TriCore, "tri-core");
+ RETURN_CASE(CPUType, X64, "intel x86-x64");
+ RETURN_CASE(CPUType, EBC, "ebc");
+ RETURN_CASE(CPUType, Thumb, "thumb");
+ RETURN_CASE(CPUType, ARMNT, "arm nt");
+ RETURN_CASE(CPUType, D3D11_Shader, "d3d11 shader");
+ }
+ return formatUnknownEnum(Cpu);
+}
+
+static std::string formatCookieKind(FrameCookieKind Kind) {
+ switch (Kind) {
+ RETURN_CASE(FrameCookieKind, Copy, "copy");
+ RETURN_CASE(FrameCookieKind, XorStackPointer, "xor stack ptr");
+ RETURN_CASE(FrameCookieKind, XorFramePointer, "xor frame ptr");
+ RETURN_CASE(FrameCookieKind, XorR13, "xor rot13");
+ }
+ return formatUnknownEnum(Kind);
+}
+
+static std::string formatRegisterId(RegisterId Id) {
+ switch (Id) {
+ RETURN_CASE(RegisterId, VFrame, "vframe");
+ RETURN_CASE(RegisterId, AL, "al");
+ RETURN_CASE(RegisterId, CL, "cl");
+ RETURN_CASE(RegisterId, DL, "dl");
+ RETURN_CASE(RegisterId, BL, "bl");
+ RETURN_CASE(RegisterId, AH, "ah");
+ RETURN_CASE(RegisterId, CH, "ch");
+ RETURN_CASE(RegisterId, DH, "dh");
+ RETURN_CASE(RegisterId, BH, "bh");
+ RETURN_CASE(RegisterId, AX, "ax");
+ RETURN_CASE(RegisterId, CX, "cx");
+ RETURN_CASE(RegisterId, DX, "dx");
+ RETURN_CASE(RegisterId, BX, "bx");
+ RETURN_CASE(RegisterId, SP, "sp");
+ RETURN_CASE(RegisterId, BP, "bp");
+ RETURN_CASE(RegisterId, SI, "si");
+ RETURN_CASE(RegisterId, DI, "di");
+ RETURN_CASE(RegisterId, EAX, "eax");
+ RETURN_CASE(RegisterId, ECX, "ecx");
+ RETURN_CASE(RegisterId, EDX, "edx");
+ RETURN_CASE(RegisterId, EBX, "ebx");
+ RETURN_CASE(RegisterId, ESP, "esp");
+ RETURN_CASE(RegisterId, EBP, "ebp");
+ RETURN_CASE(RegisterId, ESI, "esi");
+ RETURN_CASE(RegisterId, EDI, "edi");
+ RETURN_CASE(RegisterId, ES, "es");
+ RETURN_CASE(RegisterId, CS, "cs");
+ RETURN_CASE(RegisterId, SS, "ss");
+ RETURN_CASE(RegisterId, DS, "ds");
+ RETURN_CASE(RegisterId, FS, "fs");
+ RETURN_CASE(RegisterId, GS, "gs");
+ RETURN_CASE(RegisterId, IP, "ip");
+ RETURN_CASE(RegisterId, RAX, "rax");
+ RETURN_CASE(RegisterId, RBX, "rbx");
+ RETURN_CASE(RegisterId, RCX, "rcx");
+ RETURN_CASE(RegisterId, RDX, "rdx");
+ RETURN_CASE(RegisterId, RSI, "rsi");
+ RETURN_CASE(RegisterId, RDI, "rdi");
+ RETURN_CASE(RegisterId, RBP, "rbp");
+ RETURN_CASE(RegisterId, RSP, "rsp");
+ RETURN_CASE(RegisterId, R8, "r8");
+ RETURN_CASE(RegisterId, R9, "r9");
+ RETURN_CASE(RegisterId, R10, "r10");
+ RETURN_CASE(RegisterId, R11, "r11");
+ RETURN_CASE(RegisterId, R12, "r12");
+ RETURN_CASE(RegisterId, R13, "r13");
+ RETURN_CASE(RegisterId, R14, "r14");
+ RETURN_CASE(RegisterId, R15, "r15");
+ default:
+ return formatUnknownEnum(Id);
+ }
+}
+
+static std::string formatRange(LocalVariableAddrRange Range) {
+ return formatv("[{0},+{1})",
+ formatSegmentOffset(Range.ISectStart, Range.OffsetStart),
+ Range.Range)
+ .str();
+}
+
+static std::string formatGaps(uint32_t IndentLevel,
+ ArrayRef<LocalVariableAddrGap> Gaps) {
+ std::vector<std::string> GapStrs;
+ for (const auto &G : Gaps) {
+ GapStrs.push_back(formatv("({0},{1})", G.GapStartOffset, G.Range).str());
+ }
+ return typesetItemList(GapStrs, 7, IndentLevel, ", ");
+}
+
+Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record) {
+ // formatLine puts the newline at the beginning, so we use formatLine here
+ // to start a new line, and then individual visit methods use format to
+ // append to the existing line.
+ P.formatLine("- {0} [size = {1}]", getSymbolKindName(Record.Type),
+ Record.length());
+ P.Indent();
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitSymbolEnd(CVSymbol &Record) {
+ P.Unindent();
+ return Error::success();
+}
+
+std::string MinimalSymbolDumper::typeIndex(TypeIndex TI) const {
+ if (TI.isSimple())
+ return formatv("{0}", TI).str();
+ StringRef Name = Types.getTypeName(TI);
+ if (Name.size() > 32) {
+ Name = Name.take_front(32);
+ return formatv("{0} ({1}...)", TI, Name);
+ } else
+ return formatv("{0} ({1})", TI, Name);
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
+ P.format(" `{0}`", Block.Name);
+ AutoIndent Indent(P);
+ P.formatLine("parent = {0}, addr = {1}", Block.Parent,
+ formatSegmentOffset(Block.Segment, Block.CodeOffset));
+ P.formatLine("code size = {0}, end = {1}", Block.CodeSize, Block.End);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
+ P.format(" `{0}`", Thunk.Name);
+ AutoIndent Indent(P);
+ P.formatLine("parent = {0}, addr = {1}", Thunk.Parent,
+ formatSegmentOffset(Thunk.Segment, Thunk.Offset));
+ P.formatLine("kind = {0}, size = {1}, end = {2}, next = {3}",
+ formatThunkOrdinal(Thunk.Thunk), Thunk.Length, Thunk.End,
+ Thunk.Next);
+
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ TrampolineSym &Tramp) {
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, size = {1}, source = {2}, target = {3}",
+ formatTrampolineType(Tramp.Type), Tramp.Size,
+ formatSegmentOffset(Tramp.ThunkSection, Tramp.ThunkOffset),
+ formatSegmentOffset(Tramp.TargetSection, Tramp.ThunkOffset));
+
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ SectionSym &Section) {
+ P.format(" `{0}`", Section.Name);
+ AutoIndent Indent(P);
+ P.formatLine("length = {0}, alignment = {1}, rva = {2}, section # = {3}, "
+ "characteristics = {4}",
+ Section.Length, Section.Alignment, Section.Rva,
+ Section.SectionNumber, Section.Characteristics);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CoffGroupSym &CG) {
+ P.format(" `{0}`", CG.Name);
+ AutoIndent Indent(P);
+ P.formatLine("length = {0}, addr = {1}, characteristics = {2}", CG.Size,
+ formatSegmentOffset(CG.Segment, CG.Offset), CG.Characteristics);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ BPRelativeSym &BPRel) {
+ P.format(" `{0}`", BPRel.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, offset = {1}", typeIndex(BPRel.Type), BPRel.Offset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ BuildInfoSym &BuildInfo) {
+ P.format(" BuildId = `{0}`", BuildInfo.BuildId);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ CallSiteInfoSym &CSI) {
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, addr = {1}", typeIndex(CSI.Type),
+ formatSegmentOffset(CSI.Segment, CSI.CodeOffset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ EnvBlockSym &EnvBlock) {
+ for (const auto &Entry : EnvBlock.Fields) {
+ P.formatLine("- {0}", Entry);
+ }
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FileStaticSym &FS) {
+ P.format(" `{0}`", FS.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, file name offset = {1}, flags = {2}",
+ typeIndex(FS.Index), FS.ModFilenameOffset,
+ formatLocalSymFlags(P.getIndentLevel() + 9, FS.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
+ P.format(" `{0}`", Export.Name);
+ AutoIndent Indent(P);
+ P.formatLine("ordinal = {0}, flags = {1}", Export.Ordinal,
+ formatExportFlags(P.getIndentLevel() + 9, Export.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ Compile2Sym &Compile2) {
+ AutoIndent Indent(P);
+ SourceLanguage Lang = static_cast<SourceLanguage>(
+ Compile2.Flags & CompileSym2Flags::SourceLanguageMask);
+ P.formatLine("machine = {0}, ver = {1}, language = {2}",
+ formatMachineType(Compile2.Machine), Compile2.Version,
+ formatSourceLanguage(Lang));
+ P.formatLine("frontend = {0}.{1}.{2}, backend = {3}.{4}.{5}",
+ Compile2.VersionFrontendMajor, Compile2.VersionFrontendMinor,
+ Compile2.VersionFrontendBuild, Compile2.VersionBackendMajor,
+ Compile2.VersionBackendMinor, Compile2.VersionBackendBuild);
+ P.formatLine("flags = {0}",
+ formatCompileSym2Flags(P.getIndentLevel() + 9, Compile2.Flags));
+ P.formatLine(
+ "extra strings = {0}",
+ typesetStringList(P.getIndentLevel() + 9 + 2, Compile2.ExtraStrings));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ Compile3Sym &Compile3) {
+ AutoIndent Indent(P);
+ SourceLanguage Lang = static_cast<SourceLanguage>(
+ Compile3.Flags & CompileSym3Flags::SourceLanguageMask);
+ P.formatLine("machine = {0}, Ver = {1}, language = {2}",
+ formatMachineType(Compile3.Machine), Compile3.Version,
+ formatSourceLanguage(Lang));
+ P.formatLine("frontend = {0}.{1}.{2}.{3}, backend = {4}.{5}.{6}.{7}",
+ Compile3.VersionFrontendMajor, Compile3.VersionFrontendMinor,
+ Compile3.VersionFrontendBuild, Compile3.VersionFrontendQFE,
+ Compile3.VersionBackendMajor, Compile3.VersionBackendMinor,
+ Compile3.VersionBackendBuild, Compile3.VersionBackendQFE);
+ P.formatLine("flags = {0}",
+ formatCompileSym3Flags(P.getIndentLevel() + 9, Compile3.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ConstantSym &Constant) {
+ P.format(" `{0}`", Constant.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, value = {1}", typeIndex(Constant.Type),
+ Constant.Value.toString(10));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
+ P.format(" `{0}`", Data.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type),
+ formatSegmentOffset(Data.Segment, Data.DataOffset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(
+ CVSymbol &CVR, DefRangeFramePointerRelFullScopeSym &Def) {
+ P.format(" offset = {0}", Def.Offset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeFramePointerRelSym &Def) {
+ AutoIndent Indent(P);
+ P.formatLine("offset = {0}, range = {1}", Def.Offset, formatRange(Def.Range));
+ P.formatLine("gaps = {2}", Def.Offset,
+ formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeRegisterRelSym &Def) {
+ AutoIndent Indent(P);
+ P.formatLine("register = {0}, base ptr = {1}, offset in parent = {2}, has "
+ "spilled udt = {3}",
+ uint16_t(Def.Hdr.Register), int32_t(Def.Hdr.BasePointerOffset),
+ Def.offsetInParent(), Def.hasSpilledUDTMember());
+ P.formatLine("range = {0}, gaps = {1}", formatRange(Def.Range),
+ formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(
+ CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
+ AutoIndent Indent(P);
+ P.formatLine("register = {0}, may have no name = {1}, range start = "
+ "{2}, length = {3}",
+ uint16_t(DefRangeRegister.Hdr.Register),
+ uint16_t(DefRangeRegister.Hdr.MayHaveNoName),
+ formatSegmentOffset(DefRangeRegister.Range.ISectStart,
+ DefRangeRegister.Range.OffsetStart),
+ DefRangeRegister.Range.Range);
+ P.formatLine("gaps = [{0}]",
+ formatGaps(P.getIndentLevel() + 9, DefRangeRegister.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSubfieldRegisterSym &Def) {
+ AutoIndent Indent(P);
+ bool NoName = !!(Def.Hdr.MayHaveNoName == 0);
+ P.formatLine("register = {0}, may have no name = {1}, offset in parent = {2}",
+ uint16_t(Def.Hdr.Register), NoName,
+ uint32_t(Def.Hdr.OffsetInParent));
+ P.formatLine("range = {0}, gaps = {1}", formatRange(Def.Range),
+ formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ DefRangeSubfieldSym &Def) {
+ AutoIndent Indent(P);
+ P.formatLine("program = {0}, offset in parent = {1}, range = {2}",
+ Def.Program, Def.OffsetInParent, formatRange(Def.Range));
+ P.formatLine("gaps = {0}", formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, DefRangeSym &Def) {
+ AutoIndent Indent(P);
+ P.formatLine("program = {0}, range = {1}", Def.Program,
+ formatRange(Def.Range));
+ P.formatLine("gaps = {0}", formatGaps(P.getIndentLevel() + 9, Def.Gaps));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameCookieSym &FC) {
+ AutoIndent Indent(P);
+ P.formatLine("code offset = {0}, Register = {1}, kind = {2}, flags = {3}",
+ FC.CodeOffset, FC.Register, formatCookieKind(FC.CookieKind),
+ FC.Flags);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, FrameProcSym &FP) {
+ AutoIndent Indent(P);
+ P.formatLine("size = {0}, padding size = {1}, offset to padding = {2}",
+ FP.TotalFrameBytes, FP.PaddingFrameBytes, FP.OffsetToPadding);
+ P.formatLine("bytes of callee saved registers = {0}, exception handler addr "
+ "= {1}",
+ FP.BytesOfCalleeSavedRegisters,
+ formatSegmentOffset(FP.SectionIdOfExceptionHandler,
+ FP.OffsetOfExceptionHandler));
+ P.formatLine("flags = {0}",
+ formatFrameProcedureOptions(P.getIndentLevel() + 9, FP.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ HeapAllocationSiteSym &HAS) {
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, addr = {1} call size = {2}", typeIndex(HAS.Type),
+ formatSegmentOffset(HAS.Segment, HAS.CodeOffset),
+ HAS.CallInstructionSize);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, InlineSiteSym &IS) {
+ AutoIndent Indent(P);
+ auto Bytes = makeArrayRef(IS.AnnotationData);
+ StringRef Annotations(reinterpret_cast<const char *>(Bytes.begin()),
+ Bytes.size());
+
+ P.formatLine("inlinee = {0}, parent = {1}, end = {2}", typeIndex(IS.Inlinee),
+ IS.Parent, IS.End);
+ P.formatLine("annotations = {0}", toHex(Annotations));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ RegisterSym &Register) {
+ P.format(" `{0}`", Register.Name);
+ AutoIndent Indent(P);
+ P.formatLine("register = {0}, type = {1}",
+ formatRegisterId(Register.Register), typeIndex(Register.Index));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ PublicSym32 &Public) {
+ P.format(" `{0}`", Public.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, addr = {1}", typeIndex(Public.Index),
+ formatSegmentOffset(Public.Segment, Public.Offset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcRefSym &PR) {
+ P.format(" `{0}`", PR.Name);
+ AutoIndent Indent(P);
+ P.formatLine("module = {0}, sum name = {1}, offset = {2}", PR.Module,
+ PR.SumName, PR.SymOffset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
+ P.format(" `{0}` (addr = {1})", Label.Name,
+ formatSegmentOffset(Label.Segment, Label.CodeOffset));
+ AutoIndent Indent(P);
+ P.formatLine("flags = {0}",
+ formatProcSymFlags(P.getIndentLevel() + 9, Label.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
+ P.format(" `{0}`", Local.Name);
+ AutoIndent Indent(P);
+
+ std::string FlagStr =
+ formatLocalSymFlags(P.getIndentLevel() + 9, Local.Flags);
+ P.formatLine("type={0}, flags = {1}", typeIndex(Local.Type), FlagStr);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ObjNameSym &ObjName) {
+ P.format(" sig={0}, `{1}`", ObjName.Signature, ObjName.Name);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
+ P.format(" `{0}`", Proc.Name);
+ AutoIndent Indent(P);
+ P.formatLine("parent = {0}, addr = {1}, code size = {2}, end = {3}",
+ Proc.Parent, formatSegmentOffset(Proc.Segment, Proc.CodeOffset),
+ Proc.CodeSize, Proc.End);
+ P.formatLine("debug start = {0}, debug end = {1}, flags = {2}", Proc.DbgStart,
+ Proc.DbgEnd,
+ formatProcSymFlags(P.getIndentLevel() + 9, Proc.Flags));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ScopeEndSym &ScopeEnd) {
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+ AutoIndent Indent(P);
+ for (const auto &I : Caller.Indices) {
+ P.formatLine("callee: {0}", typeIndex(I));
+ }
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ RegRelativeSym &RegRel) {
+ P.format(" `{0}`", RegRel.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, register = {1}, offset = {2}",
+ typeIndex(RegRel.Type), formatRegisterId(RegRel.Register),
+ RegRel.Offset);
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+ ThreadLocalDataSym &Data) {
+ P.format(" `{0}`", Data.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, addr = {1}", typeIndex(Data.Type),
+ formatSegmentOffset(Data.Segment, Data.DataOffset));
+ return Error::success();
+}
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
+ P.format(" `{0}`", UDT.Name);
+ AutoIndent Indent(P);
+ P.formatLine("original type = {0}", UDT.Type);
+ return Error::success();
+}
diff --git a/tools/llvm-pdbutil/MinimalSymbolDumper.h b/tools/llvm-pdbutil/MinimalSymbolDumper.h
new file mode 100644
index 000000000000..451f2da6fd1d
--- /dev/null
+++ b/tools/llvm-pdbutil/MinimalSymbolDumper.h
@@ -0,0 +1,47 @@
+//===- MinimalSymbolDumper.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_TOOLS_LLVMPDBUTIL_MINIMAL_SYMBOL_DUMPER_H
+#define LLVM_TOOLS_LLVMPDBUTIL_MINIMAL_SYMBOL_DUMPER_H
+
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+
+namespace llvm {
+namespace codeview {
+class LazyRandomTypeCollection;
+}
+
+namespace pdb {
+class LinePrinter;
+
+class MinimalSymbolDumper : public codeview::SymbolVisitorCallbacks {
+public:
+ MinimalSymbolDumper(LinePrinter &P, bool RecordBytes,
+ codeview::LazyRandomTypeCollection &Types)
+ : P(P), Types(Types) {}
+
+ Error visitSymbolBegin(codeview::CVSymbol &Record) override;
+ Error visitSymbolEnd(codeview::CVSymbol &Record) override;
+
+#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
+ virtual Error visitKnownRecord(codeview::CVSymbol &CVR, \
+ codeview::Name &Record) override;
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
+
+private:
+ std::string typeIndex(codeview::TypeIndex TI) const;
+
+ LinePrinter &P;
+ codeview::LazyRandomTypeCollection &Types;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif \ No newline at end of file
diff --git a/tools/llvm-pdbutil/MinimalTypeDumper.cpp b/tools/llvm-pdbutil/MinimalTypeDumper.cpp
new file mode 100644
index 000000000000..22d3a4557c52
--- /dev/null
+++ b/tools/llvm-pdbutil/MinimalTypeDumper.cpp
@@ -0,0 +1,543 @@
+//===- MinimalTypeDumper.cpp ---------------------------------- *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MinimalTypeDumper.h"
+
+#include "FormatUtil.h"
+#include "LinePrinter.h"
+
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static StringRef getLeafTypeName(TypeLeafKind K) {
+ switch (K) {
+#define TYPE_RECORD(EnumName, value, name) \
+ case EnumName: \
+ return #EnumName;
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+ default:
+ llvm_unreachable("Unknown type leaf kind!");
+ }
+ return "";
+}
+
+static std::string formatClassOptions(uint32_t IndentLevel,
+ ClassOptions Options) {
+ std::vector<std::string> Opts;
+ PUSH_FLAG(ClassOptions, HasConstructorOrDestructor, Options,
+ "has ctor / dtor");
+ PUSH_FLAG(ClassOptions, ContainsNestedClass, Options,
+ "contains nested class");
+ PUSH_FLAG(ClassOptions, HasConversionOperator, Options,
+ "conversion operator");
+ PUSH_FLAG(ClassOptions, ForwardReference, Options, "forward ref");
+ PUSH_FLAG(ClassOptions, HasUniqueName, Options, "has unique name");
+ PUSH_FLAG(ClassOptions, Intrinsic, Options, "intrin");
+ PUSH_FLAG(ClassOptions, Nested, Options, "is nested");
+ PUSH_FLAG(ClassOptions, HasOverloadedOperator, Options,
+ "overloaded operator");
+ PUSH_FLAG(ClassOptions, HasOverloadedAssignmentOperator, Options,
+ "overloaded operator=");
+ PUSH_FLAG(ClassOptions, Packed, Options, "packed");
+ PUSH_FLAG(ClassOptions, Scoped, Options, "scoped");
+ PUSH_FLAG(ClassOptions, Sealed, Options, "sealed");
+
+ return typesetItemList(Opts, 4, IndentLevel, " | ");
+}
+
+static std::string pointerOptions(PointerOptions Options) {
+ std::vector<std::string> Opts;
+ PUSH_FLAG(PointerOptions, Flat32, Options, "flat32");
+ PUSH_FLAG(PointerOptions, Volatile, Options, "volatile");
+ PUSH_FLAG(PointerOptions, Const, Options, "const");
+ PUSH_FLAG(PointerOptions, Unaligned, Options, "unaligned");
+ PUSH_FLAG(PointerOptions, Restrict, Options, "restrict");
+ PUSH_FLAG(PointerOptions, WinRTSmartPointer, Options, "winrt");
+ if (Opts.empty())
+ return "None";
+ return join(Opts, " | ");
+}
+
+static std::string modifierOptions(ModifierOptions Options) {
+ std::vector<std::string> Opts;
+ PUSH_FLAG(ModifierOptions, Const, Options, "const");
+ PUSH_FLAG(ModifierOptions, Volatile, Options, "volatile");
+ PUSH_FLAG(ModifierOptions, Unaligned, Options, "unaligned");
+ if (Opts.empty())
+ return "None";
+ return join(Opts, " | ");
+}
+
+static std::string formatCallingConvention(CallingConvention Convention) {
+ switch (Convention) {
+ RETURN_CASE(CallingConvention, AlphaCall, "alphacall");
+ RETURN_CASE(CallingConvention, AM33Call, "am33call");
+ RETURN_CASE(CallingConvention, ArmCall, "armcall");
+ RETURN_CASE(CallingConvention, ClrCall, "clrcall");
+ RETURN_CASE(CallingConvention, FarC, "far cdecl");
+ RETURN_CASE(CallingConvention, FarFast, "far fastcall");
+ RETURN_CASE(CallingConvention, FarPascal, "far pascal");
+ RETURN_CASE(CallingConvention, FarStdCall, "far stdcall");
+ RETURN_CASE(CallingConvention, FarSysCall, "far syscall");
+ RETURN_CASE(CallingConvention, Generic, "generic");
+ RETURN_CASE(CallingConvention, Inline, "inline");
+ RETURN_CASE(CallingConvention, M32RCall, "m32rcall");
+ RETURN_CASE(CallingConvention, MipsCall, "mipscall");
+ RETURN_CASE(CallingConvention, NearC, "cdecl");
+ RETURN_CASE(CallingConvention, NearFast, "fastcall");
+ RETURN_CASE(CallingConvention, NearPascal, "pascal");
+ RETURN_CASE(CallingConvention, NearStdCall, "stdcall");
+ RETURN_CASE(CallingConvention, NearSysCall, "near syscall");
+ RETURN_CASE(CallingConvention, NearVector, "vectorcall");
+ RETURN_CASE(CallingConvention, PpcCall, "ppccall");
+ RETURN_CASE(CallingConvention, SHCall, "shcall");
+ RETURN_CASE(CallingConvention, SH5Call, "sh5call");
+ RETURN_CASE(CallingConvention, ThisCall, "thiscall");
+ RETURN_CASE(CallingConvention, TriCall, "tricall");
+ }
+ return formatUnknownEnum(Convention);
+}
+
+static std::string formatPointerMode(PointerMode Mode) {
+ switch (Mode) {
+ RETURN_CASE(PointerMode, LValueReference, "ref");
+ RETURN_CASE(PointerMode, Pointer, "pointer");
+ RETURN_CASE(PointerMode, PointerToDataMember, "data member pointer");
+ RETURN_CASE(PointerMode, PointerToMemberFunction, "member fn pointer");
+ RETURN_CASE(PointerMode, RValueReference, "rvalue ref");
+ }
+ return formatUnknownEnum(Mode);
+}
+
+static std::string memberAccess(MemberAccess Access) {
+ switch (Access) {
+ RETURN_CASE(MemberAccess, None, "");
+ RETURN_CASE(MemberAccess, Private, "private");
+ RETURN_CASE(MemberAccess, Protected, "protected");
+ RETURN_CASE(MemberAccess, Public, "public");
+ }
+ return formatUnknownEnum(Access);
+}
+
+static std::string methodKind(MethodKind Kind) {
+ switch (Kind) {
+ RETURN_CASE(MethodKind, Vanilla, "");
+ RETURN_CASE(MethodKind, Virtual, "virtual");
+ RETURN_CASE(MethodKind, Static, "static");
+ RETURN_CASE(MethodKind, Friend, "friend");
+ RETURN_CASE(MethodKind, IntroducingVirtual, "intro virtual");
+ RETURN_CASE(MethodKind, PureVirtual, "pure virtual");
+ RETURN_CASE(MethodKind, PureIntroducingVirtual, "pure intro virtual");
+ }
+ return formatUnknownEnum(Kind);
+}
+
+static std::string pointerKind(PointerKind Kind) {
+ switch (Kind) {
+ RETURN_CASE(PointerKind, Near16, "ptr16");
+ RETURN_CASE(PointerKind, Far16, "far ptr16");
+ RETURN_CASE(PointerKind, Huge16, "huge ptr16");
+ RETURN_CASE(PointerKind, BasedOnSegment, "segment based");
+ RETURN_CASE(PointerKind, BasedOnValue, "value based");
+ RETURN_CASE(PointerKind, BasedOnSegmentValue, "segment value based");
+ RETURN_CASE(PointerKind, BasedOnAddress, "address based");
+ RETURN_CASE(PointerKind, BasedOnSegmentAddress, "segment address based");
+ RETURN_CASE(PointerKind, BasedOnType, "type based");
+ RETURN_CASE(PointerKind, BasedOnSelf, "self based");
+ RETURN_CASE(PointerKind, Near32, "ptr32");
+ RETURN_CASE(PointerKind, Far32, "far ptr32");
+ RETURN_CASE(PointerKind, Near64, "ptr64");
+ }
+ return formatUnknownEnum(Kind);
+}
+
+static std::string memberAttributes(const MemberAttributes &Attrs) {
+ std::vector<std::string> Opts;
+ std::string Access = memberAccess(Attrs.getAccess());
+ std::string Kind = methodKind(Attrs.getMethodKind());
+ if (!Access.empty())
+ Opts.push_back(Access);
+ if (!Kind.empty())
+ Opts.push_back(Kind);
+ MethodOptions Flags = Attrs.getFlags();
+ PUSH_FLAG(MethodOptions, Pseudo, Flags, "pseudo");
+ PUSH_FLAG(MethodOptions, NoInherit, Flags, "noinherit");
+ PUSH_FLAG(MethodOptions, NoConstruct, Flags, "noconstruct");
+ PUSH_FLAG(MethodOptions, CompilerGenerated, Flags, "compiler-generated");
+ PUSH_FLAG(MethodOptions, Sealed, Flags, "sealed");
+ return join(Opts, " ");
+}
+
+static std::string formatPointerAttrs(const PointerRecord &Record) {
+ PointerMode Mode = Record.getMode();
+ PointerOptions Opts = Record.getOptions();
+ PointerKind Kind = Record.getPointerKind();
+ return formatv("mode = {0}, opts = {1}, kind = {2}", formatPointerMode(Mode),
+ pointerOptions(Opts), pointerKind(Kind));
+}
+
+static std::string formatFunctionOptions(FunctionOptions Options) {
+ std::vector<std::string> Opts;
+
+ PUSH_FLAG(FunctionOptions, CxxReturnUdt, Options, "returns cxx udt");
+ PUSH_FLAG(FunctionOptions, ConstructorWithVirtualBases, Options,
+ "constructor with virtual bases");
+ PUSH_FLAG(FunctionOptions, Constructor, Options, "constructor");
+ if (Opts.empty())
+ return "None";
+ return join(Opts, " | ");
+}
+
+Error MinimalTypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
+ // formatLine puts the newline at the beginning, so we use formatLine here
+ // to start a new line, and then individual visit methods use format to
+ // append to the existing line.
+ if (!Hashes) {
+ P.formatLine("{0} | {1} [size = {2}]",
+ fmt_align(Index, AlignStyle::Right, Width),
+ getLeafTypeName(Record.Type), Record.length());
+ } else {
+ std::string H;
+ if (Index.toArrayIndex() >= HashValues.size())
+ H = "(not present)";
+ else
+ H = utostr(HashValues[Index.toArrayIndex()]);
+ P.formatLine("{0} | {1} [size = {2}, hash = {3}]",
+ fmt_align(Index, AlignStyle::Right, Width),
+ getLeafTypeName(Record.Type), Record.length(), H);
+ }
+ P.Indent(Width + 3);
+ return Error::success();
+}
+Error MinimalTypeDumpVisitor::visitTypeEnd(CVType &Record) {
+ P.Unindent(Width + 3);
+ if (RecordBytes) {
+ AutoIndent Indent(P, 9);
+ P.formatBinary("Bytes", Record.RecordData, 0);
+ }
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitMemberBegin(CVMemberRecord &Record) {
+ P.formatLine("- {0}", getLeafTypeName(Record.Kind));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitMemberEnd(CVMemberRecord &Record) {
+ if (RecordBytes) {
+ AutoIndent Indent(P, 2);
+ P.formatBinary("Bytes", Record.Data, 0);
+ }
+ return Error::success();
+}
+
+StringRef MinimalTypeDumpVisitor::getTypeName(TypeIndex TI) const {
+ if (TI.isNoneType())
+ return "";
+ return Types.getTypeName(TI);
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ FieldListRecord &FieldList) {
+ if (auto EC = codeview::visitMemberRecordStream(FieldList.Data, *this))
+ return EC;
+
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ StringIdRecord &String) {
+ P.format(" ID: {0}, String: {1}", String.getId(), String.getString());
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ArgListRecord &Args) {
+ auto Indices = Args.getIndices();
+ if (Indices.empty())
+ return Error::success();
+
+ auto Max = std::max_element(Indices.begin(), Indices.end());
+ uint32_t W = NumDigits(Max->getIndex()) + 2;
+
+ for (auto I : Indices)
+ P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
+ getTypeName(I));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ StringListRecord &Strings) {
+ auto Indices = Strings.getIndices();
+ if (Indices.empty())
+ return Error::success();
+
+ auto Max = std::max_element(Indices.begin(), Indices.end());
+ uint32_t W = NumDigits(Max->getIndex()) + 2;
+
+ for (auto I : Indices)
+ P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
+ getTypeName(I));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ClassRecord &Class) {
+ P.formatLine("class name: `{0}`", Class.Name);
+ if (Class.hasUniqueName())
+ P.formatLine("unique name: `{0}`", Class.UniqueName);
+ P.formatLine("vtable: {0}, base list: {1}, field list: {2}",
+ Class.VTableShape, Class.DerivationList, Class.FieldList);
+ P.formatLine("options: {0}",
+ formatClassOptions(P.getIndentLevel(), Class.Options));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UnionRecord &Union) {
+ P.formatLine("class name: `{0}`", Union.Name);
+ if (Union.hasUniqueName())
+ P.formatLine("unique name: `{0}`", Union.UniqueName);
+ P.formatLine("field list: {0}", Union.FieldList);
+ P.formatLine("options: {0}",
+ formatClassOptions(P.getIndentLevel(), Union.Options));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
+ P.formatLine("name: `{0}`", Enum.Name);
+ if (Enum.hasUniqueName())
+ P.formatLine("unique name: `{0}`", Enum.UniqueName);
+ P.formatLine("field list: {0}, underlying type: {1}", Enum.FieldList,
+ Enum.UnderlyingType);
+ P.formatLine("options: {0}",
+ formatClassOptions(P.getIndentLevel(), Enum.Options));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
+ if (AT.Name.empty()) {
+ P.formatLine("size: {0}, index type: {1}, element type: {2}", AT.Size,
+ AT.IndexType, AT.ElementType);
+ } else {
+ P.formatLine("name: {0}, size: {1}, index type: {2}, element type: {3}",
+ AT.Name, AT.Size, AT.IndexType, AT.ElementType);
+ }
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ VFTableRecord &VFT) {
+ P.formatLine("offset: {0}, complete class: {1}, overridden vftable: {2}",
+ VFT.VFPtrOffset, VFT.CompleteClass, VFT.OverriddenVFTable);
+ P.formatLine("method names: ");
+ if (!VFT.MethodNames.empty()) {
+ std::string Sep =
+ formatv("\n{0}",
+ fmt_repeat(' ', P.getIndentLevel() + strlen("method names: ")))
+ .str();
+ P.print(join(VFT.MethodNames, Sep));
+ }
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ MemberFuncIdRecord &Id) {
+ P.formatLine("name = {0}, type = {1}, class type = {2}", Id.Name,
+ Id.FunctionType, Id.ClassType);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ProcedureRecord &Proc) {
+ P.formatLine("return type = {0}, # args = {1}, param list = {2}",
+ Proc.ReturnType, Proc.ParameterCount, Proc.ArgumentList);
+ P.formatLine("calling conv = {0}, options = {1}",
+ formatCallingConvention(Proc.CallConv),
+ formatFunctionOptions(Proc.Options));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ MemberFunctionRecord &MF) {
+ P.formatLine("return type = {0}, # args = {1}, param list = {2}",
+ MF.ParameterCount, MF.ArgumentList, MF.ReturnType);
+ P.formatLine("class type = {0}, this type = {1}, this adjust = {2}",
+ MF.ClassType, MF.ThisType, MF.ThisPointerAdjustment);
+ P.formatLine("calling conv = {0}, options = {1}",
+ formatCallingConvention(MF.CallConv),
+ formatFunctionOptions(MF.Options));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ FuncIdRecord &Func) {
+ P.formatLine("name = {0}, type = {1}, parent scope = {2}", Func.Name,
+ Func.FunctionType, Func.ParentScope);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ TypeServer2Record &TS) {
+ P.formatLine("name = {0}, age = {1}, guid = {2}", TS.Name, TS.Age,
+ fmt_guid(TS.Guid));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ PointerRecord &Ptr) {
+ P.formatLine("referent = {0}, {1}", Ptr.ReferentType,
+ formatPointerAttrs(Ptr));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ ModifierRecord &Mod) {
+ P.formatLine("referent = {0}, modifiers = {1}", Mod.ModifiedType,
+ modifierOptions(Mod.Modifiers));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ VFTableShapeRecord &Shape) {
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtModSourceLineRecord &U) {
+ P.formatLine("udt = {0}, mod = {1}, file = {2}, line = {3}", U.UDT, U.Module,
+ U.SourceFile.getIndex(), U.LineNumber);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ UdtSourceLineRecord &U) {
+ P.formatLine("udt = {0}, file = {1}, line = {2}", U.UDT,
+ U.SourceFile.getIndex(), U.LineNumber);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ BitFieldRecord &BF) {
+ P.formatLine("type = {0}, bit offset = {1}, # bits = {2}", BF.Type,
+ BF.BitOffset, BF.BitSize);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(
+ CVType &CVR, MethodOverloadListRecord &Overloads) {
+ for (auto &M : Overloads.Methods)
+ P.formatLine("- Method [type = {0}, vftable offset = {1}, attrs = {2}]",
+ M.Type, M.VFTableOffset, memberAttributes(M.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR,
+ BuildInfoRecord &BI) {
+ auto Indices = BI.ArgIndices;
+ if (Indices.empty())
+ return Error::success();
+
+ auto Max = std::max_element(Indices.begin(), Indices.end());
+ uint32_t W = NumDigits(Max->getIndex()) + 2;
+
+ for (auto I : Indices)
+ P.formatLine("{0}: `{1}`", fmt_align(I, AlignStyle::Right, W),
+ getTypeName(I));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) {
+ std::string Type = (R.Mode == LabelType::Far) ? "far" : "near";
+ P.format(" type = {0}", Type);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Nested) {
+ P.format(" [name = `{0}`, parent = {1}]", Nested.Name, Nested.Type);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OneMethodRecord &Method) {
+ P.format(" [name = `{0}`]", Method.Name);
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, vftable offset = {1}, attrs = {2}", Method.Type,
+ Method.VFTableOffset, memberAttributes(Method.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ OverloadedMethodRecord &Method) {
+ P.format(" [name = `{0}`, # overloads = {1}, overload list = {2}]",
+ Method.Name, Method.NumOverloads, Method.MethodList);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ DataMemberRecord &Field) {
+ P.format(" [name = `{0}`, Type = {1}, offset = {2}, attrs = {3}]", Field.Name,
+ Field.Type, Field.FieldOffset, memberAttributes(Field.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ StaticDataMemberRecord &Field) {
+ P.format(" [name = `{0}`, type = {1}, attrs = {2}]", Field.Name, Field.Type,
+ memberAttributes(Field.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ EnumeratorRecord &Enum) {
+ P.format(" [{0} = {1}]", Enum.Name,
+ Enum.Value.toString(10, Enum.Value.isSigned()));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ BaseClassRecord &Base) {
+ AutoIndent Indent(P);
+ P.formatLine("type = {0}, offset = {1}, attrs = {2}", Base.Type, Base.Offset,
+ memberAttributes(Base.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VirtualBaseClassRecord &Base) {
+ AutoIndent Indent(P);
+ P.formatLine(
+ "base = {0}, vbptr = {1}, vbptr offset = {2}, vtable index = {3}",
+ Base.BaseType, Base.VBPtrType, Base.VBPtrOffset, Base.VTableIndex);
+ P.formatLine("attrs = {0}", memberAttributes(Base.Attrs));
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ ListContinuationRecord &Cont) {
+ P.format(" continuation = {0}", Cont.ContinuationIndex);
+ return Error::success();
+}
+
+Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
+ VFPtrRecord &VFP) {
+ P.format(" type = {0}", VFP.Type);
+ return Error::success();
+}
diff --git a/tools/llvm-pdbutil/MinimalTypeDumper.h b/tools/llvm-pdbutil/MinimalTypeDumper.h
new file mode 100644
index 000000000000..42882b4b4060
--- /dev/null
+++ b/tools/llvm-pdbutil/MinimalTypeDumper.h
@@ -0,0 +1,61 @@
+//===- MinimalTypeDumper.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_TOOLS_LLVMPDBUTIL_MINIMAL_TYPE_DUMPER_H
+#define LLVM_TOOLS_LLVMPDBUTIL_MINIMAL_TYPE_DUMPER_H
+
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/BinaryStreamArray.h"
+
+namespace llvm {
+namespace codeview {
+class LazyRandomTypeCollection;
+}
+
+namespace pdb {
+class LinePrinter;
+
+class MinimalTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
+public:
+ MinimalTypeDumpVisitor(LinePrinter &P, uint32_t Width, bool RecordBytes,
+ bool Hashes, codeview::LazyRandomTypeCollection &Types,
+ FixedStreamArray<support::ulittle32_t> HashValues)
+ : P(P), Width(Width), RecordBytes(RecordBytes), Hashes(Hashes),
+ Types(Types), HashValues(HashValues) {}
+
+ Error visitTypeBegin(codeview::CVType &Record,
+ codeview::TypeIndex Index) override;
+ Error visitTypeEnd(codeview::CVType &Record) override;
+ Error visitMemberBegin(codeview::CVMemberRecord &Record) override;
+ Error visitMemberEnd(codeview::CVMemberRecord &Record) override;
+
+#define TYPE_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownRecord(codeview::CVType &CVR, \
+ codeview::Name##Record &Record) override;
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ Error visitKnownMember(codeview::CVMemberRecord &CVR, \
+ codeview::Name##Record &Record) override;
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+
+private:
+ StringRef getTypeName(codeview::TypeIndex TI) const;
+
+ LinePrinter &P;
+ uint32_t Width;
+ bool RecordBytes = false;
+ bool Hashes = false;
+ codeview::LazyRandomTypeCollection &Types;
+ FixedStreamArray<support::ulittle32_t> HashValues;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp b/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
index 54e33683f552..66c29fc5d4ee 100644
--- a/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
+++ b/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
@@ -151,21 +151,21 @@ bool PrettyClassLayoutGraphicalDumper::shouldRecurse() const {
}
void PrettyClassLayoutGraphicalDumper::dump(const PDBSymbolData &Symbol) {
- assert(CurrentItem != nullptr);
-
- DataMemberLayoutItem &Layout =
- static_cast<DataMemberLayoutItem &>(*CurrentItem);
-
VariableDumper VarDumper(Printer);
VarDumper.start(Symbol, ClassOffsetZero);
- if (Layout.hasUDTLayout() && shouldRecurse()) {
- uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
- Printer.Indent();
- PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
- ChildOffsetZero);
- TypeDumper.start(Layout.getUDTLayout());
- Printer.Unindent();
+ if (CurrentItem != nullptr) {
+ DataMemberLayoutItem &Layout =
+ static_cast<DataMemberLayoutItem &>(*CurrentItem);
+
+ if (Layout.hasUDTLayout() && shouldRecurse()) {
+ uint32_t ChildOffsetZero = ClassOffsetZero + Layout.getOffsetInParent();
+ Printer.Indent();
+ PrettyClassLayoutGraphicalDumper TypeDumper(Printer, RecursionLevel + 1,
+ ChildOffsetZero);
+ TypeDumper.start(Layout.getUDTLayout());
+ Printer.Unindent();
+ }
}
DumpedAnything = true;
diff --git a/tools/llvm-pdbutil/RawOutputStyle.cpp b/tools/llvm-pdbutil/RawOutputStyle.cpp
new file mode 100644
index 000000000000..b204a89ec317
--- /dev/null
+++ b/tools/llvm-pdbutil/RawOutputStyle.cpp
@@ -0,0 +1,1064 @@
+//===- RawOutputStyle.cpp ------------------------------------ *- C++ --*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RawOutputStyle.h"
+
+#include "CompactTypeDumpVisitor.h"
+#include "FormatUtil.h"
+#include "MinimalSymbolDumper.h"
+#include "MinimalTypeDumper.h"
+#include "StreamUtil.h"
+#include "llvm-pdbutil.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/Formatters.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolDumper.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/EnumTables.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawError.h"
+#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+
+#include <unordered_map>
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::msf;
+using namespace llvm::pdb;
+
+RawOutputStyle::RawOutputStyle(PDBFile &File)
+ : File(File), P(2, false, outs()) {}
+
+Error RawOutputStyle::dump() {
+ if (opts::raw::DumpSummary) {
+ if (auto EC = dumpFileSummary())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::raw::DumpStreams) {
+ if (auto EC = dumpStreamSummary())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::raw::DumpBlockRange.hasValue()) {
+ if (auto EC = dumpBlockRanges())
+ return EC;
+ P.NewLine();
+ }
+
+ if (!opts::raw::DumpStreamData.empty()) {
+ if (auto EC = dumpStreamBytes())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::raw::DumpStringTable) {
+ if (auto EC = dumpStringTable())
+ return EC;
+ P.NewLine();
+ }
+
+ if (opts::raw::DumpModules) {
+ if (auto EC = dumpModules())
+ return EC;
+ }
+
+ if (opts::raw::DumpModuleFiles) {
+ if (auto EC = dumpModuleFiles())
+ return EC;
+ }
+
+ if (opts::raw::DumpLines) {
+ if (auto EC = dumpLines())
+ return EC;
+ }
+
+ if (opts::raw::DumpInlineeLines) {
+ if (auto EC = dumpInlineeLines())
+ return EC;
+ }
+
+ if (opts::raw::DumpXmi) {
+ if (auto EC = dumpXmi())
+ return EC;
+ }
+
+ if (opts::raw::DumpXme) {
+ if (auto EC = dumpXme())
+ return EC;
+ }
+
+ if (opts::raw::DumpTypes || opts::raw::DumpTypeExtras) {
+ if (auto EC = dumpTpiStream(StreamTPI))
+ return EC;
+ }
+
+ if (opts::raw::DumpIds || opts::raw::DumpIdExtras) {
+ if (auto EC = dumpTpiStream(StreamIPI))
+ return EC;
+ }
+
+ if (opts::raw::DumpPublics) {
+ if (auto EC = dumpPublics())
+ return EC;
+ }
+
+ if (opts::raw::DumpSymbols) {
+ if (auto EC = dumpModuleSyms())
+ return EC;
+ }
+
+ if (opts::raw::DumpSectionContribs) {
+ if (auto EC = dumpSectionContribs())
+ return EC;
+ }
+
+ if (opts::raw::DumpSectionMap) {
+ if (auto EC = dumpSectionMap())
+ return EC;
+ }
+
+ return Error::success();
+}
+
+static void printHeader(LinePrinter &P, const Twine &S) {
+ P.NewLine();
+ P.formatLine("{0,=60}", S);
+ P.formatLine("{0}", fmt_repeat('=', 60));
+}
+
+Error RawOutputStyle::dumpFileSummary() {
+ printHeader(P, "Summary");
+
+ ExitOnError Err("Invalid PDB Format");
+
+ AutoIndent Indent(P);
+ P.formatLine("Block Size: {0}", File.getBlockSize());
+ P.formatLine("Number of blocks: {0}", File.getBlockCount());
+ P.formatLine("Number of streams: {0}", File.getNumStreams());
+
+ auto &PS = Err(File.getPDBInfoStream());
+ P.formatLine("Signature: {0}", PS.getSignature());
+ P.formatLine("Age: {0}", PS.getAge());
+ P.formatLine("GUID: {0}", fmt_guid(PS.getGuid().Guid));
+ P.formatLine("Features: {0:x+}", static_cast<uint32_t>(PS.getFeatures()));
+ P.formatLine("Has Debug Info: {0}", File.hasPDBDbiStream());
+ P.formatLine("Has Types: {0}", File.hasPDBTpiStream());
+ P.formatLine("Has IDs: {0}", File.hasPDBIpiStream());
+ P.formatLine("Has Globals: {0}", File.hasPDBGlobalsStream());
+ P.formatLine("Has Publics: {0}", File.hasPDBPublicsStream());
+ if (File.hasPDBDbiStream()) {
+ auto &DBI = Err(File.getPDBDbiStream());
+ P.formatLine("Is incrementally linked: {0}", DBI.isIncrementallyLinked());
+ P.formatLine("Has conflicting types: {0}", DBI.hasCTypes());
+ P.formatLine("Is stripped: {0}", DBI.isStripped());
+ }
+
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpStreamSummary() {
+ printHeader(P, "Streams");
+
+ if (StreamPurposes.empty())
+ discoverStreamPurposes(File, StreamPurposes);
+
+ AutoIndent Indent(P);
+ uint32_t StreamCount = File.getNumStreams();
+
+ for (uint16_t StreamIdx = 0; StreamIdx < StreamCount; ++StreamIdx) {
+ P.formatLine(
+ "Stream {0}: [{1}] ({2} bytes)",
+ fmt_align(StreamIdx, AlignStyle::Right, NumDigits(StreamCount)),
+ StreamPurposes[StreamIdx], File.getStreamByteSize(StreamIdx));
+ }
+
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpBlockRanges() {
+ printHeader(P, "MSF Blocks");
+
+ auto &R = *opts::raw::DumpBlockRange;
+ uint32_t Max = R.Max.getValueOr(R.Min);
+
+ AutoIndent Indent(P);
+ if (Max < R.Min)
+ return make_error<StringError>(
+ "Invalid block range specified. Max < Min",
+ std::make_error_code(std::errc::bad_address));
+ if (Max >= File.getBlockCount())
+ return make_error<StringError>(
+ "Invalid block range specified. Requested block out of bounds",
+ std::make_error_code(std::errc::bad_address));
+
+ for (uint32_t I = R.Min; I <= Max; ++I) {
+ auto ExpectedData = File.getBlockData(I, File.getBlockSize());
+ if (!ExpectedData)
+ return ExpectedData.takeError();
+ std::string Label = formatv("Block {0}", I).str();
+ P.formatBinary(Label, *ExpectedData, 0);
+ }
+
+ return Error::success();
+}
+
+static Error parseStreamSpec(StringRef Str, uint32_t &SI, uint32_t &Offset,
+ uint32_t &Size) {
+ if (Str.consumeInteger(0, SI))
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "Invalid Stream Specification");
+ if (Str.consume_front(":")) {
+ if (Str.consumeInteger(0, Offset))
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "Invalid Stream Specification");
+ }
+ if (Str.consume_front("@")) {
+ if (Str.consumeInteger(0, Size))
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "Invalid Stream Specification");
+ }
+ if (!Str.empty())
+ return make_error<RawError>(raw_error_code::invalid_format,
+ "Invalid Stream Specification");
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpStreamBytes() {
+ if (StreamPurposes.empty())
+ discoverStreamPurposes(File, StreamPurposes);
+
+ printHeader(P, "Stream Data");
+ ExitOnError Err("Unexpected error reading stream data");
+
+ for (auto &Str : opts::raw::DumpStreamData) {
+ uint32_t SI = 0;
+ uint32_t Begin = 0;
+ uint32_t Size = 0;
+ uint32_t End = 0;
+
+ if (auto EC = parseStreamSpec(Str, SI, Begin, Size))
+ return EC;
+
+ AutoIndent Indent(P);
+ if (SI >= File.getNumStreams()) {
+ P.formatLine("Stream {0}: Not present", SI);
+ continue;
+ }
+
+ auto S = MappedBlockStream::createIndexedStream(
+ File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator());
+ if (!S) {
+ P.NewLine();
+ P.formatLine("Stream {0}: Not present", SI);
+ continue;
+ }
+
+ if (Size == 0)
+ End = S->getLength();
+ else
+ End = std::min(Begin + Size, S->getLength());
+
+ P.formatLine("Stream {0} ({1:N} bytes): {2}", SI, S->getLength(),
+ StreamPurposes[SI]);
+ AutoIndent Indent2(P);
+
+ BinaryStreamReader R(*S);
+ ArrayRef<uint8_t> StreamData;
+ Err(R.readBytes(StreamData, S->getLength()));
+ Size = End - Begin;
+ StreamData = StreamData.slice(Begin, Size);
+ P.formatBinary("Data", StreamData, Begin);
+ }
+ return Error::success();
+}
+
+static Expected<ModuleDebugStreamRef> getModuleDebugStream(PDBFile &File,
+ uint32_t Index) {
+ ExitOnError Err("Unexpected error");
+
+ auto &Dbi = Err(File.getPDBDbiStream());
+ const auto &Modules = Dbi.modules();
+ auto Modi = Modules.getModuleDescriptor(Index);
+
+ uint16_t ModiStream = Modi.getModuleStreamIndex();
+ if (ModiStream == kInvalidStreamIndex)
+ return make_error<RawError>(raw_error_code::no_stream,
+ "Module stream not present");
+
+ auto ModStreamData = MappedBlockStream::createIndexedStream(
+ File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
+ File.getAllocator());
+
+ ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
+ if (auto EC = ModS.reload())
+ return make_error<RawError>(raw_error_code::corrupt_file,
+ "Invalid module stream");
+
+ return std::move(ModS);
+}
+
+static std::string formatChecksumKind(FileChecksumKind Kind) {
+ switch (Kind) {
+ RETURN_CASE(FileChecksumKind, None, "None");
+ RETURN_CASE(FileChecksumKind, MD5, "MD5");
+ RETURN_CASE(FileChecksumKind, SHA1, "SHA-1");
+ RETURN_CASE(FileChecksumKind, SHA256, "SHA-256");
+ }
+ return formatUnknownEnum(Kind);
+}
+
+namespace {
+class StringsAndChecksumsPrinter {
+ const DebugStringTableSubsectionRef &extractStringTable(PDBFile &File) {
+ ExitOnError Err("Unexpected error processing modules");
+ return Err(File.getStringTable()).getStringTable();
+ }
+
+ template <typename... Args>
+ void formatInternal(LinePrinter &Printer, bool Append,
+ Args &&... args) const {
+ if (Append)
+ Printer.format(std::forward<Args>(args)...);
+ else
+ Printer.formatLine(std::forward<Args>(args)...);
+ }
+
+public:
+ StringsAndChecksumsPrinter(PDBFile &File, uint32_t Modi)
+ : Records(extractStringTable(File)) {
+ auto MDS = getModuleDebugStream(File, Modi);
+ if (!MDS) {
+ consumeError(MDS.takeError());
+ return;
+ }
+
+ DebugStream = llvm::make_unique<ModuleDebugStreamRef>(std::move(*MDS));
+ Records.initialize(MDS->subsections());
+ if (Records.hasChecksums()) {
+ for (const auto &Entry : Records.checksums()) {
+ auto S = Records.strings().getString(Entry.FileNameOffset);
+ if (!S)
+ continue;
+ ChecksumsByFile[*S] = Entry;
+ }
+ }
+ }
+
+ Expected<StringRef> getNameFromStringTable(uint32_t Offset) const {
+ return Records.strings().getString(Offset);
+ }
+
+ void formatFromFileName(LinePrinter &Printer, StringRef File,
+ bool Append = false) const {
+ auto FC = ChecksumsByFile.find(File);
+ if (FC == ChecksumsByFile.end()) {
+ formatInternal(Printer, Append, "- (no checksum) {0}", File);
+ return;
+ }
+
+ formatInternal(Printer, Append, "- ({0}: {1}) {2}",
+ formatChecksumKind(FC->getValue().Kind),
+ toHex(FC->getValue().Checksum), File);
+ }
+
+ void formatFromChecksumsOffset(LinePrinter &Printer, uint32_t Offset,
+ bool Append = false) const {
+ if (!Records.hasChecksums()) {
+ formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
+ return;
+ }
+
+ auto Iter = Records.checksums().getArray().at(Offset);
+ if (Iter == Records.checksums().getArray().end()) {
+ formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
+ return;
+ }
+
+ uint32_t FO = Iter->FileNameOffset;
+ auto ExpectedFile = getNameFromStringTable(FO);
+ if (!ExpectedFile) {
+ formatInternal(Printer, Append, "(unknown file name offset {0})", Offset);
+ consumeError(ExpectedFile.takeError());
+ return;
+ }
+ if (Iter->Kind == FileChecksumKind::None) {
+ formatInternal(Printer, Append, "{0} (no checksum)", *ExpectedFile);
+ } else {
+ formatInternal(Printer, Append, "{0} ({1}: {2})", *ExpectedFile,
+ formatChecksumKind(Iter->Kind), toHex(Iter->Checksum));
+ }
+ }
+
+ std::unique_ptr<ModuleDebugStreamRef> DebugStream;
+ StringsAndChecksumsRef Records;
+ StringMap<FileChecksumEntry> ChecksumsByFile;
+};
+} // namespace
+
+template <typename CallbackT>
+static void iterateModules(PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
+ CallbackT Callback) {
+ AutoIndent Indent(P);
+ if (!File.hasPDBDbiStream()) {
+ P.formatLine("DBI Stream not present");
+ return;
+ }
+
+ ExitOnError Err("Unexpected error processing modules");
+
+ auto &Stream = Err(File.getPDBDbiStream());
+
+ const DbiModuleList &Modules = Stream.modules();
+ uint32_t Count = Modules.getModuleCount();
+ uint32_t Digits = NumDigits(Count);
+ for (uint32_t I = 0; I < Count; ++I) {
+ auto Modi = Modules.getModuleDescriptor(I);
+ P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
+ Modi.getModuleName());
+
+ StringsAndChecksumsPrinter Strings(File, I);
+ AutoIndent Indent2(P, IndentLevel);
+ Callback(I, Strings);
+ }
+}
+
+template <typename SubsectionT>
+static void iterateModuleSubsections(
+ PDBFile &File, LinePrinter &P, uint32_t IndentLevel,
+ llvm::function_ref<void(uint32_t, StringsAndChecksumsPrinter &,
+ SubsectionT &)>
+ Callback) {
+
+ iterateModules(
+ File, P, IndentLevel,
+ [&File, &Callback](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
+ auto MDS = getModuleDebugStream(File, Modi);
+ if (!MDS) {
+ consumeError(MDS.takeError());
+ return;
+ }
+
+ for (const auto &SS : MDS->subsections()) {
+ SubsectionT Subsection;
+
+ if (SS.kind() != Subsection.kind())
+ continue;
+
+ BinaryStreamReader Reader(SS.getRecordData());
+ if (auto EC = Subsection.initialize(Reader))
+ continue;
+ Callback(Modi, Strings, Subsection);
+ }
+ });
+}
+
+Error RawOutputStyle::dumpModules() {
+ printHeader(P, "Modules");
+
+ AutoIndent Indent(P);
+ if (!File.hasPDBDbiStream()) {
+ P.formatLine("DBI Stream not present");
+ return Error::success();
+ }
+
+ ExitOnError Err("Unexpected error processing modules");
+
+ auto &Stream = Err(File.getPDBDbiStream());
+
+ const DbiModuleList &Modules = Stream.modules();
+ uint32_t Count = Modules.getModuleCount();
+ uint32_t Digits = NumDigits(Count);
+ for (uint32_t I = 0; I < Count; ++I) {
+ auto Modi = Modules.getModuleDescriptor(I);
+ P.formatLine("Mod {0:4} | Name: `{1}`: ",
+ fmt_align(I, AlignStyle::Right, Digits), Modi.getModuleName());
+ P.formatLine(" Obj: `{0}`: ", Modi.getObjFileName());
+ P.formatLine(" debug stream: {0}, # files: {1}, has ec info: {2}",
+ Modi.getModuleStreamIndex(), Modi.getNumberOfFiles(),
+ Modi.hasECInfo());
+ }
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpModuleFiles() {
+ printHeader(P, "Files");
+
+ ExitOnError Err("Unexpected error processing modules");
+
+ iterateModules(
+ File, P, 11,
+ [this, &Err](uint32_t Modi, StringsAndChecksumsPrinter &Strings) {
+ auto &Stream = Err(File.getPDBDbiStream());
+
+ const DbiModuleList &Modules = Stream.modules();
+ for (const auto &F : Modules.source_files(Modi)) {
+ Strings.formatFromFileName(P, F);
+ }
+ });
+ return Error::success();
+}
+
+static void typesetLinesAndColumns(PDBFile &File, LinePrinter &P,
+ uint32_t Start, const LineColumnEntry &E) {
+ const uint32_t kMaxCharsPerLineNumber = 4; // 4 digit line number
+ uint32_t MinColumnWidth = kMaxCharsPerLineNumber + 5;
+
+ // Let's try to keep it under 100 characters
+ constexpr uint32_t kMaxRowLength = 100;
+ // At least 3 spaces between columns.
+ uint32_t ColumnsPerRow = kMaxRowLength / (MinColumnWidth + 3);
+ uint32_t ItemsLeft = E.LineNumbers.size();
+ auto LineIter = E.LineNumbers.begin();
+ while (ItemsLeft != 0) {
+ uint32_t RowColumns = std::min(ItemsLeft, ColumnsPerRow);
+ for (uint32_t I = 0; I < RowColumns; ++I) {
+ LineInfo Line(LineIter->Flags);
+ std::string LineStr;
+ if (Line.isAlwaysStepInto())
+ LineStr = "ASI";
+ else if (Line.isNeverStepInto())
+ LineStr = "NSI";
+ else
+ LineStr = utostr(Line.getStartLine());
+ char Statement = Line.isStatement() ? ' ' : '!';
+ P.format("{0} {1:X-} {2} ",
+ fmt_align(LineStr, AlignStyle::Right, kMaxCharsPerLineNumber),
+ fmt_align(Start + LineIter->Offset, AlignStyle::Right, 8, '0'),
+ Statement);
+ ++LineIter;
+ --ItemsLeft;
+ }
+ P.NewLine();
+ }
+}
+
+Error RawOutputStyle::dumpLines() {
+ printHeader(P, "Lines");
+
+ uint32_t LastModi = UINT32_MAX;
+ uint32_t LastNameIndex = UINT32_MAX;
+ iterateModuleSubsections<DebugLinesSubsectionRef>(
+ File, P, 4,
+ [this, &LastModi, &LastNameIndex](uint32_t Modi,
+ StringsAndChecksumsPrinter &Strings,
+ DebugLinesSubsectionRef &Lines) {
+ uint16_t Segment = Lines.header()->RelocSegment;
+ uint32_t Begin = Lines.header()->RelocOffset;
+ uint32_t End = Begin + Lines.header()->CodeSize;
+ for (const auto &Block : Lines) {
+ if (LastModi != Modi || LastNameIndex != Block.NameIndex) {
+ LastModi = Modi;
+ LastNameIndex = Block.NameIndex;
+ Strings.formatFromChecksumsOffset(P, Block.NameIndex);
+ }
+
+ AutoIndent Indent(P, 2);
+ P.formatLine("{0:X-4}:{1:X-8}-{2:X-8}, ", Segment, Begin, End);
+ uint32_t Count = Block.LineNumbers.size();
+ if (Lines.hasColumnInfo())
+ P.format("line/column/addr entries = {0}", Count);
+ else
+ P.format("line/addr entries = {0}", Count);
+
+ P.NewLine();
+ typesetLinesAndColumns(File, P, Begin, Block);
+ }
+ });
+
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpInlineeLines() {
+ printHeader(P, "Inlinee Lines");
+
+ iterateModuleSubsections<DebugInlineeLinesSubsectionRef>(
+ File, P, 2,
+ [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
+ DebugInlineeLinesSubsectionRef &Lines) {
+ P.formatLine("{0,+8} | {1,+5} | {2}", "Inlinee", "Line", "Source File");
+ for (const auto &Entry : Lines) {
+ P.formatLine("{0,+8} | {1,+5} | ", Entry.Header->Inlinee,
+ fmtle(Entry.Header->SourceLineNum));
+ Strings.formatFromChecksumsOffset(P, Entry.Header->FileID, true);
+ }
+ P.NewLine();
+ });
+
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpXmi() {
+ printHeader(P, "Cross Module Imports");
+ iterateModuleSubsections<DebugCrossModuleImportsSubsectionRef>(
+ File, P, 2,
+ [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
+ DebugCrossModuleImportsSubsectionRef &Imports) {
+ P.formatLine("{0,=32} | {1}", "Imported Module", "Type IDs");
+
+ for (const auto &Xmi : Imports) {
+ auto ExpectedModule =
+ Strings.getNameFromStringTable(Xmi.Header->ModuleNameOffset);
+ StringRef Module;
+ SmallString<32> ModuleStorage;
+ if (!ExpectedModule) {
+ Module = "(unknown module)";
+ consumeError(ExpectedModule.takeError());
+ } else
+ Module = *ExpectedModule;
+ if (Module.size() > 32) {
+ ModuleStorage = "...";
+ ModuleStorage += Module.take_back(32 - 3);
+ Module = ModuleStorage;
+ }
+ std::vector<std::string> TIs;
+ for (const auto I : Xmi.Imports)
+ TIs.push_back(formatv("{0,+10:X+}", fmtle(I)));
+ std::string Result =
+ typesetItemList(TIs, P.getIndentLevel() + 35, 12, " ");
+ P.formatLine("{0,+32} | {1}", Module, Result);
+ }
+ });
+
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpXme() {
+ printHeader(P, "Cross Module Exports");
+
+ iterateModuleSubsections<DebugCrossModuleExportsSubsectionRef>(
+ File, P, 2,
+ [this](uint32_t Modi, StringsAndChecksumsPrinter &Strings,
+ DebugCrossModuleExportsSubsectionRef &Exports) {
+ P.formatLine("{0,-10} | {1}", "Local ID", "Global ID");
+ for (const auto &Export : Exports) {
+ P.formatLine("{0,+10:X+} | {1}", TypeIndex(Export.Local),
+ TypeIndex(Export.Global));
+ }
+ });
+
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpStringTable() {
+ printHeader(P, "String Table");
+
+ AutoIndent Indent(P);
+ auto IS = File.getStringTable();
+ if (!IS) {
+ P.formatLine("Not present in file");
+ consumeError(IS.takeError());
+ return Error::success();
+ }
+
+ if (IS->name_ids().empty()) {
+ P.formatLine("Empty");
+ return Error::success();
+ }
+
+ auto MaxID = std::max_element(IS->name_ids().begin(), IS->name_ids().end());
+ uint32_t Digits = NumDigits(*MaxID);
+
+ P.formatLine("{0} | {1}", fmt_align("ID", AlignStyle::Right, Digits),
+ "String");
+
+ std::vector<uint32_t> SortedIDs(IS->name_ids().begin(), IS->name_ids().end());
+ std::sort(SortedIDs.begin(), SortedIDs.end());
+ for (uint32_t I : SortedIDs) {
+ auto ES = IS->getStringForID(I);
+ llvm::SmallString<32> Str;
+ if (!ES) {
+ consumeError(ES.takeError());
+ Str = "Error reading string";
+ } else if (!ES->empty()) {
+ Str.append("'");
+ Str.append(*ES);
+ Str.append("'");
+ }
+
+ if (!Str.empty())
+ P.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Digits), Str);
+ }
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
+ assert(StreamIdx == StreamTPI || StreamIdx == StreamIPI);
+
+ bool Present = false;
+ bool DumpTypes = false;
+ bool DumpBytes = false;
+ bool DumpExtras = false;
+ if (StreamIdx == StreamTPI) {
+ printHeader(P, "Types (TPI Stream)");
+ Present = File.hasPDBTpiStream();
+ DumpTypes = opts::raw::DumpTypes;
+ DumpBytes = opts::raw::DumpTypeData;
+ DumpExtras = opts::raw::DumpTypeExtras;
+ } else if (StreamIdx == StreamIPI) {
+ printHeader(P, "Types (IPI Stream)");
+ Present = File.hasPDBIpiStream();
+ DumpTypes = opts::raw::DumpIds;
+ DumpBytes = opts::raw::DumpIdData;
+ DumpExtras = opts::raw::DumpIdExtras;
+ }
+
+ AutoIndent Indent(P);
+ if (!Present) {
+ P.formatLine("Stream not present");
+ return Error::success();
+ }
+
+ ExitOnError Err("Unexpected error processing types");
+
+ auto &Stream = Err((StreamIdx == StreamTPI) ? File.getPDBTpiStream()
+ : File.getPDBIpiStream());
+
+ auto &Types = Err(initializeTypeDatabase(StreamIdx));
+
+ if (DumpTypes) {
+ P.formatLine("Showing {0:N} records", Stream.getNumTypeRecords());
+ uint32_t Width =
+ NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
+
+ MinimalTypeDumpVisitor V(P, Width + 2, DumpBytes, DumpExtras, Types,
+ Stream.getHashValues());
+
+ Optional<TypeIndex> I = Types.getFirst();
+ if (auto EC = codeview::visitTypeStream(Types, V)) {
+ P.formatLine("An error occurred dumping type records: {0}",
+ toString(std::move(EC)));
+ }
+ }
+
+ if (DumpExtras) {
+ P.NewLine();
+ auto IndexOffsets = Stream.getTypeIndexOffsets();
+ P.formatLine("Type Index Offsets:");
+ for (const auto &IO : IndexOffsets) {
+ AutoIndent Indent2(P);
+ P.formatLine("TI: {0}, Offset: {1}", IO.Type, fmtle(IO.Offset));
+ }
+
+ P.NewLine();
+ P.formatLine("Hash Adjusters:");
+ auto &Adjusters = Stream.getHashAdjusters();
+ auto &Strings = Err(File.getStringTable());
+ for (const auto &A : Adjusters) {
+ AutoIndent Indent2(P);
+ auto ExpectedStr = Strings.getStringForID(A.first);
+ TypeIndex TI(A.second);
+ if (ExpectedStr)
+ P.formatLine("`{0}` -> {1}", *ExpectedStr, TI);
+ else {
+ P.formatLine("unknown str id ({0}) -> {1}", A.first, TI);
+ consumeError(ExpectedStr.takeError());
+ }
+ }
+ }
+ return Error::success();
+}
+
+Expected<codeview::LazyRandomTypeCollection &>
+RawOutputStyle::initializeTypeDatabase(uint32_t SN) {
+ auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes;
+ auto Tpi =
+ (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream();
+ if (!Tpi)
+ return Tpi.takeError();
+
+ if (!TypeCollection) {
+ auto &Types = Tpi->typeArray();
+ uint32_t Count = Tpi->getNumTypeRecords();
+ auto Offsets = Tpi->getTypeIndexOffsets();
+ TypeCollection =
+ llvm::make_unique<LazyRandomTypeCollection>(Types, Count, Offsets);
+ }
+
+ return *TypeCollection;
+}
+
+Error RawOutputStyle::dumpModuleSyms() {
+ printHeader(P, "Symbols");
+
+ AutoIndent Indent(P);
+ if (!File.hasPDBDbiStream()) {
+ P.formatLine("DBI Stream not present");
+ return Error::success();
+ }
+
+ ExitOnError Err("Unexpected error processing symbols");
+
+ auto &Stream = Err(File.getPDBDbiStream());
+
+ auto &Types = Err(initializeTypeDatabase(StreamTPI));
+
+ const DbiModuleList &Modules = Stream.modules();
+ uint32_t Count = Modules.getModuleCount();
+ uint32_t Digits = NumDigits(Count);
+ for (uint32_t I = 0; I < Count; ++I) {
+ auto Modi = Modules.getModuleDescriptor(I);
+ P.formatLine("Mod {0:4} | `{1}`: ", fmt_align(I, AlignStyle::Right, Digits),
+ Modi.getModuleName());
+ uint16_t ModiStream = Modi.getModuleStreamIndex();
+ if (ModiStream == kInvalidStreamIndex) {
+ P.formatLine(" <symbols not present>");
+ continue;
+ }
+ auto ModStreamData = MappedBlockStream::createIndexedStream(
+ File.getMsfLayout(), File.getMsfBuffer(), ModiStream,
+ File.getAllocator());
+
+ ModuleDebugStreamRef ModS(Modi, std::move(ModStreamData));
+ if (auto EC = ModS.reload()) {
+ P.formatLine("Error loading module stream {0}. {1}", I,
+ toString(std::move(EC)));
+ continue;
+ }
+
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::raw::DumpSymRecordBytes, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+ if (auto EC = Visitor.visitSymbolStream(ModS.getSymbolArray())) {
+ P.formatLine("Error while processing symbol records. {0}",
+ toString(std::move(EC)));
+ continue;
+ }
+ }
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpPublics() {
+ printHeader(P, "Public Symbols");
+
+ AutoIndent Indent(P);
+ if (!File.hasPDBPublicsStream()) {
+ P.formatLine("Publics stream not present");
+ return Error::success();
+ }
+
+ ExitOnError Err("Error dumping publics stream");
+
+ auto &Types = Err(initializeTypeDatabase(StreamTPI));
+ auto &Publics = Err(File.getPDBPublicsStream());
+ SymbolVisitorCallbackPipeline Pipeline;
+ SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+ MinimalSymbolDumper Dumper(P, opts::raw::DumpSymRecordBytes, Types);
+
+ Pipeline.addCallbackToPipeline(Deserializer);
+ Pipeline.addCallbackToPipeline(Dumper);
+ CVSymbolVisitor Visitor(Pipeline);
+ auto ExpectedSymbols = Publics.getSymbolArray();
+ if (!ExpectedSymbols) {
+ P.formatLine("Could not read public symbol record stream");
+ return Error::success();
+ }
+
+ if (auto EC = Visitor.visitSymbolStream(*ExpectedSymbols))
+ P.formatLine("Error while processing public symbol records. {0}",
+ toString(std::move(EC)));
+
+ return Error::success();
+}
+
+static std::string formatSectionCharacteristics(uint32_t IndentLevel,
+ uint32_t C) {
+ using SC = COFF::SectionCharacteristics;
+ std::vector<std::string> Opts;
+ if (C == COFF::SC_Invalid)
+ return "invalid";
+ if (C == 0)
+ return "none";
+
+ PUSH_FLAG(SC, IMAGE_SCN_TYPE_NOLOAD, C, "IMAGE_SCN_TYPE_NOLOAD");
+ PUSH_FLAG(SC, IMAGE_SCN_TYPE_NO_PAD, C, "IMAGE_SCN_TYPE_NO_PAD");
+ PUSH_FLAG(SC, IMAGE_SCN_CNT_CODE, C, "IMAGE_SCN_CNT_CODE");
+ PUSH_FLAG(SC, IMAGE_SCN_CNT_INITIALIZED_DATA, C,
+ "IMAGE_SCN_CNT_INITIALIZED_DATA");
+ PUSH_FLAG(SC, IMAGE_SCN_CNT_UNINITIALIZED_DATA, C,
+ "IMAGE_SCN_CNT_UNINITIALIZED_DATA");
+ PUSH_FLAG(SC, IMAGE_SCN_LNK_OTHER, C, "IMAGE_SCN_LNK_OTHER");
+ PUSH_FLAG(SC, IMAGE_SCN_LNK_INFO, C, "IMAGE_SCN_LNK_INFO");
+ PUSH_FLAG(SC, IMAGE_SCN_LNK_REMOVE, C, "IMAGE_SCN_LNK_REMOVE");
+ PUSH_FLAG(SC, IMAGE_SCN_LNK_COMDAT, C, "IMAGE_SCN_LNK_COMDAT");
+ PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_PURGEABLE, C, "IMAGE_SCN_MEM_PURGEABLE");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_16BIT, C, "IMAGE_SCN_MEM_16BIT");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_LOCKED, C, "IMAGE_SCN_MEM_LOCKED");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_PRELOAD, C, "IMAGE_SCN_MEM_PRELOAD");
+ PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
+ PUSH_FLAG(SC, IMAGE_SCN_GPREL, C, "IMAGE_SCN_GPREL");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1BYTES, C,
+ "IMAGE_SCN_ALIGN_1BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2BYTES, C,
+ "IMAGE_SCN_ALIGN_2BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4BYTES, C,
+ "IMAGE_SCN_ALIGN_4BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8BYTES, C,
+ "IMAGE_SCN_ALIGN_8BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_16BYTES, C,
+ "IMAGE_SCN_ALIGN_16BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_32BYTES, C,
+ "IMAGE_SCN_ALIGN_32BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_64BYTES, C,
+ "IMAGE_SCN_ALIGN_64BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_128BYTES, C,
+ "IMAGE_SCN_ALIGN_128BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_256BYTES, C,
+ "IMAGE_SCN_ALIGN_256BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_512BYTES, C,
+ "IMAGE_SCN_ALIGN_512BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_1024BYTES, C,
+ "IMAGE_SCN_ALIGN_1024BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_2048BYTES, C,
+ "IMAGE_SCN_ALIGN_2048BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_4096BYTES, C,
+ "IMAGE_SCN_ALIGN_4096BYTES");
+ PUSH_MASKED_FLAG(SC, 0xF00000, IMAGE_SCN_ALIGN_8192BYTES, C,
+ "IMAGE_SCN_ALIGN_8192BYTES");
+ PUSH_FLAG(SC, IMAGE_SCN_LNK_NRELOC_OVFL, C, "IMAGE_SCN_LNK_NRELOC_OVFL");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_DISCARDABLE, C, "IMAGE_SCN_MEM_DISCARDABLE");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_CACHED, C, "IMAGE_SCN_MEM_NOT_CACHED");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_NOT_PAGED, C, "IMAGE_SCN_MEM_NOT_PAGED");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_SHARED, C, "IMAGE_SCN_MEM_SHARED");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ");
+ PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE");
+ return typesetItemList(Opts, IndentLevel, 3, " | ");
+}
+
+static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
+ OMFSegDescFlags Flags) {
+ std::vector<std::string> Opts;
+ if (Flags == OMFSegDescFlags::None)
+ return "none";
+
+ PUSH_FLAG(OMFSegDescFlags, Read, Flags, "read");
+ PUSH_FLAG(OMFSegDescFlags, Write, Flags, "write");
+ PUSH_FLAG(OMFSegDescFlags, Execute, Flags, "execute");
+ PUSH_FLAG(OMFSegDescFlags, AddressIs32Bit, Flags, "32 bit addr");
+ PUSH_FLAG(OMFSegDescFlags, IsSelector, Flags, "selector");
+ PUSH_FLAG(OMFSegDescFlags, IsAbsoluteAddress, Flags, "absolute addr");
+ PUSH_FLAG(OMFSegDescFlags, IsGroup, Flags, "group");
+ return typesetItemList(Opts, IndentLevel, 4, " | ");
+}
+
+Error RawOutputStyle::dumpSectionContribs() {
+ printHeader(P, "Section Contributions");
+ ExitOnError Err("Error dumping publics stream");
+
+ AutoIndent Indent(P);
+ if (!File.hasPDBDbiStream()) {
+ P.formatLine(
+ "Section contribs require a DBI Stream, which could not be loaded");
+ return Error::success();
+ }
+
+ auto &Dbi = Err(File.getPDBDbiStream());
+
+ class Visitor : public ISectionContribVisitor {
+ public:
+ Visitor(LinePrinter &P) : P(P) {}
+ void visit(const SectionContrib &SC) override {
+ P.formatLine(
+ "SC | mod = {2}, {0}, size = {1}, data crc = {3}, reloc crc = {4}",
+ formatSegmentOffset(SC.ISect, SC.Off), fmtle(SC.Size), fmtle(SC.Imod),
+ fmtle(SC.DataCrc), fmtle(SC.RelocCrc));
+ P.formatLine(" {0}",
+ formatSectionCharacteristics(P.getIndentLevel() + 6,
+ SC.Characteristics));
+ }
+ void visit(const SectionContrib2 &SC) override {
+ P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
+ "crc = {4}, coff section = {5}",
+ formatSegmentOffset(SC.Base.ISect, SC.Base.Off),
+ fmtle(SC.Base.Size), fmtle(SC.Base.Imod),
+ fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
+ fmtle(SC.ISectCoff));
+ P.formatLine(" {0}",
+ formatSectionCharacteristics(P.getIndentLevel() + 6,
+ SC.Base.Characteristics));
+ }
+
+ private:
+ LinePrinter &P;
+ };
+
+ Visitor V(P);
+ Dbi.visitSectionContributions(V);
+ return Error::success();
+}
+
+Error RawOutputStyle::dumpSectionMap() {
+ printHeader(P, "Section Map");
+ ExitOnError Err("Error dumping section map");
+
+ AutoIndent Indent(P);
+ if (!File.hasPDBDbiStream()) {
+ P.formatLine("Dumping the section map requires a DBI Stream, which could "
+ "not be loaded");
+ return Error::success();
+ }
+
+ auto &Dbi = Err(File.getPDBDbiStream());
+
+ uint32_t I = 0;
+ for (auto &M : Dbi.getSectionMap()) {
+ P.formatLine(
+ "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I,
+ fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
+ P.formatLine(" class = {0}, offset = {1}, size = {2}",
+ fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
+ P.formatLine(" flags = {0}",
+ formatSegMapDescriptorFlag(
+ P.getIndentLevel() + 13,
+ static_cast<OMFSegDescFlags>(uint16_t(M.Flags))));
+ ++I;
+ }
+ return Error::success();
+}
diff --git a/tools/llvm-pdbutil/LLVMOutputStyle.h b/tools/llvm-pdbutil/RawOutputStyle.h
index 184dc4e1f44d..803f588961bb 100644
--- a/tools/llvm-pdbutil/LLVMOutputStyle.h
+++ b/tools/llvm-pdbutil/RawOutputStyle.h
@@ -1,4 +1,4 @@
-//===- LLVMOutputStyle.h -------------------------------------- *- C++ --*-===//
+//===- RawOutputStyle.h -------------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,15 +7,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
-#define LLVM_TOOLS_LLVMPDBDUMP_LLVMOUTPUTSTYLE_H
+#ifndef LLVM_TOOLS_LLVMPDBDUMP_RAWOUTPUTSTYLE_H
+#define LLVM_TOOLS_LLVMPDBDUMP_RAWOUTPUTSTYLE_H
+#include "LinePrinter.h"
#include "OutputStyle.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
-#include "llvm/Support/ScopedPrinter.h"
#include <string>
@@ -27,9 +27,9 @@ class LazyRandomTypeCollection;
}
namespace pdb {
-class LLVMOutputStyle : public OutputStyle {
+class RawOutputStyle : public OutputStyle {
public:
- LLVMOutputStyle(PDBFile &File);
+ RawOutputStyle(PDBFile &File);
Error dump() override;
@@ -37,34 +37,30 @@ private:
Expected<codeview::LazyRandomTypeCollection &>
initializeTypeDatabase(uint32_t SN);
- Error dumpFileHeaders();
+ Error dumpFileSummary();
Error dumpStreamSummary();
- Error dumpFreePageMap();
Error dumpBlockRanges();
- Error dumpGlobalsStream();
Error dumpStreamBytes();
- Error dumpStreamBlocks();
Error dumpStringTable();
- Error dumpInfoStream();
+ Error dumpLines();
+ Error dumpInlineeLines();
+ Error dumpXmi();
+ Error dumpXme();
Error dumpTpiStream(uint32_t StreamIdx);
- Error dumpDbiStream();
+ Error dumpModules();
+ Error dumpModuleFiles();
+ Error dumpModuleSyms();
+ Error dumpPublics();
Error dumpSectionContribs();
Error dumpSectionMap();
- Error dumpPublicsStream();
- Error dumpSectionHeaders();
- Error dumpFpoStream();
-
- void dumpBitVector(StringRef Name, const BitVector &V);
-
- void flush();
PDBFile &File;
- ScopedPrinter P;
+ LinePrinter P;
std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
std::unique_ptr<codeview::LazyRandomTypeCollection> IpiTypes;
SmallVector<std::string, 32> StreamPurposes;
};
-}
-}
+} // namespace pdb
+} // namespace llvm
#endif
diff --git a/tools/llvm-pdbutil/YAMLOutputStyle.cpp b/tools/llvm-pdbutil/YAMLOutputStyle.cpp
index 58c538d968c8..ae3138efb13a 100644
--- a/tools/llvm-pdbutil/YAMLOutputStyle.cpp
+++ b/tools/llvm-pdbutil/YAMLOutputStyle.cpp
@@ -18,6 +18,7 @@
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
@@ -31,6 +32,13 @@ using namespace llvm;
using namespace llvm::codeview;
using namespace llvm::pdb;
+static bool checkModuleSubsection(opts::ModuleSubsection MS) {
+ return any_of(opts::pdb2yaml::DumpModuleSubsections,
+ [=](opts::ModuleSubsection M) {
+ return M == MS || M == opts::ModuleSubsection::All;
+ });
+}
+
YAMLOutputStyle::YAMLOutputStyle(PDBFile &File)
: File(File), Out(outs()), Obj(File.getAllocator()) {
Out.setWriteDefaultValues(!opts::pdb2yaml::Minimal);
@@ -92,8 +100,8 @@ Error YAMLOutputStyle::dumpFileHeaders() {
}
Error YAMLOutputStyle::dumpStringTable() {
- bool RequiresStringTable = opts::shared::DumpModuleFiles ||
- !opts::shared::DumpModuleSubsections.empty();
+ bool RequiresStringTable = opts::pdb2yaml::DumpModuleFiles ||
+ !opts::pdb2yaml::DumpModuleSubsections.empty();
bool RequestedStringTable = opts::pdb2yaml::StringTable;
if (!RequiresStringTable && !RequestedStringTable)
return Error::success();
@@ -200,7 +208,7 @@ Error YAMLOutputStyle::dumpDbiStream() {
Obj.DbiStream->PdbDllRbld = DS.getPdbDllRbld();
Obj.DbiStream->PdbDllVersion = DS.getPdbDllVersion();
Obj.DbiStream->VerHeader = DS.getDbiVersion();
- if (opts::shared::DumpModules) {
+ if (opts::pdb2yaml::DumpModules) {
const auto &Modules = DS.modules();
for (uint32_t I = 0; I < Modules.getModuleCount(); ++I) {
DbiModuleDescriptor MI = Modules.getModuleDescriptor(I);
@@ -210,7 +218,7 @@ Error YAMLOutputStyle::dumpDbiStream() {
DMI.Mod = MI.getModuleName();
DMI.Obj = MI.getObjFileName();
- if (opts::shared::DumpModuleFiles) {
+ if (opts::pdb2yaml::DumpModuleFiles) {
auto Files = Modules.source_files(I);
DMI.SourceFiles.assign(Files.begin(), Files.end());
}
@@ -230,27 +238,29 @@ Error YAMLOutputStyle::dumpDbiStream() {
auto ExpectedST = File.getStringTable();
if (!ExpectedST)
return ExpectedST.takeError();
- if (!opts::shared::DumpModuleSubsections.empty() &&
+ if (!opts::pdb2yaml::DumpModuleSubsections.empty() &&
ModS.hasDebugSubsections()) {
auto ExpectedChecksums = ModS.findChecksumsSubsection();
if (!ExpectedChecksums)
return ExpectedChecksums.takeError();
+ StringsAndChecksumsRef SC(ExpectedST->getStringTable(),
+ *ExpectedChecksums);
+
for (const auto &SS : ModS.subsections()) {
opts::ModuleSubsection OptionKind = convertSubsectionKind(SS.kind());
- if (!opts::checkModuleSubsection(OptionKind))
+ if (!checkModuleSubsection(OptionKind))
continue;
auto Converted =
- CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(
- ExpectedST->getStringTable(), *ExpectedChecksums, SS);
+ CodeViewYAML::YAMLDebugSubsection::fromCodeViewSubection(SC, SS);
if (!Converted)
return Converted.takeError();
DMI.Subsections.push_back(*Converted);
}
}
- if (opts::shared::DumpModuleSyms) {
+ if (opts::pdb2yaml::DumpModuleSyms) {
DMI.Modi.emplace();
DMI.Modi->Signature = ModS.signature();
@@ -293,6 +303,12 @@ Error YAMLOutputStyle::dumpIpiStream() {
if (!opts::pdb2yaml::IpiStream)
return Error::success();
+ auto InfoS = File.getPDBInfoStream();
+ if (!InfoS)
+ return InfoS.takeError();
+ if (!InfoS->containsIdStream())
+ return Error::success();
+
auto IpiS = File.getPDBIpiStream();
if (!IpiS)
return IpiS.takeError();
diff --git a/tools/llvm-pdbutil/llvm-pdbutil.cpp b/tools/llvm-pdbutil/llvm-pdbutil.cpp
index f6b6a156a767..9088783876e0 100644
--- a/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -15,7 +15,6 @@
#include "Analyze.h"
#include "Diff.h"
-#include "LLVMOutputStyle.h"
#include "LinePrinter.h"
#include "OutputStyle.h"
#include "PrettyCompilandDumper.h"
@@ -23,6 +22,7 @@
#include "PrettyFunctionDumper.h"
#include "PrettyTypeDumper.h"
#include "PrettyVariableDumper.h"
+#include "RawOutputStyle.h"
#include "YAMLOutputStyle.h"
#include "llvm/ADT/ArrayRef.h"
@@ -35,6 +35,7 @@
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
@@ -265,6 +266,8 @@ cl::list<std::string> InputFilenames(cl::Positional,
cl::OneOrMore, cl::sub(DiffSubcommand));
}
+cl::OptionCategory FileOptions("Module & File Options");
+
namespace raw {
cl::OptionCategory MsfOptions("MSF Container Options");
@@ -273,18 +276,11 @@ cl::OptionCategory SymbolOptions("Symbol Options");
cl::OptionCategory MiscOptions("Miscellaneous Options");
// MSF OPTIONS
-cl::opt<bool> DumpHeaders("headers", cl::desc("dump PDB headers"),
+cl::opt<bool> DumpSummary("summary", cl::desc("dump file summary"),
+ cl::cat(MsfOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpStreams("streams",
+ cl::desc("dump summary of the PDB streams"),
cl::cat(MsfOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpStreamBlocks("stream-blocks",
- cl::desc("dump PDB stream blocks"),
- cl::cat(MsfOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpStreamSummary("stream-summary",
- cl::desc("dump summary of the PDB streams"),
- cl::cat(MsfOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpPageStats(
- "page-stats",
- cl::desc("dump allocation stats of the pages in the MSF file"),
- cl::cat(MsfOptions), cl::sub(RawSubcommand));
cl::opt<std::string>
DumpBlockRangeOpt("block-data", cl::value_desc("start[-end]"),
cl::desc("Dump binary data from specified range."),
@@ -298,40 +294,67 @@ cl::list<std::string>
cl::cat(MsfOptions), cl::sub(RawSubcommand));
// TYPE OPTIONS
-cl::opt<bool>
- CompactRecords("compact-records",
- cl::desc("Dump type and symbol records with less detail"),
- cl::cat(TypeOptions), cl::sub(RawSubcommand));
-
-cl::opt<bool>
- DumpTpiRecords("tpi-records",
- cl::desc("dump CodeView type records from TPI stream"),
- cl::cat(TypeOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpTpiRecordBytes(
- "tpi-record-bytes",
+cl::opt<bool> DumpTypes("types",
+ cl::desc("dump CodeView type records from TPI stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpTypeData(
+ "type-data",
cl::desc("dump CodeView type record raw bytes from TPI stream"),
cl::cat(TypeOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"),
- cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
+cl::opt<bool> DumpTypeExtras("type-extras",
+ cl::desc("dump type hashes and index offsets"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
+cl::opt<bool> DumpIds("ids",
+ cl::desc("dump CodeView type records from IPI stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
cl::opt<bool>
- DumpIpiRecords("ipi-records",
- cl::desc("dump CodeView type records from IPI stream"),
- cl::cat(TypeOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpIpiRecordBytes(
- "ipi-record-bytes",
- cl::desc("dump CodeView type record raw bytes from IPI stream"),
- cl::cat(TypeOptions), cl::sub(RawSubcommand));
+ DumpIdData("id-data",
+ cl::desc("dump CodeView type record raw bytes from IPI stream"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
+cl::opt<bool> DumpIdExtras("id-extras",
+ cl::desc("dump id hashes and index offsets"),
+ cl::cat(TypeOptions), cl::sub(RawSubcommand));
// SYMBOL OPTIONS
-cl::opt<bool> DumpGlobals("globals", cl::desc("dump globals stream data"),
- cl::cat(SymbolOptions), cl::sub(RawSubcommand));
cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpSymbols("symbols", cl::desc("dump module symbols"),
+ cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+
cl::opt<bool>
- DumpSymRecordBytes("sym-record-bytes",
+ DumpSymRecordBytes("sym-data",
cl::desc("dump CodeView symbol record raw bytes"),
cl::cat(SymbolOptions), cl::sub(RawSubcommand));
+// MODULE & FILE OPTIONS
+cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpModuleFiles(
+ "files",
+ cl::desc("Dump the source files that contribute to each module's."),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpLines(
+ "l",
+ cl::desc("dump source file/line information (DEBUG_S_LINES subsection)"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpInlineeLines(
+ "il",
+ cl::desc("dump inlinee line information (DEBUG_S_INLINEELINES subsection)"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpXmi(
+ "xmi",
+ cl::desc(
+ "dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS subsection)"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+cl::opt<bool> DumpXme(
+ "xme",
+ cl::desc(
+ "dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS subsection)"),
+ cl::cat(FileOptions), cl::sub(RawSubcommand));
+
// MISCELLANEOUS OPTIONS
cl::opt<bool> DumpStringTable("string-table", cl::desc("dump PDB String Table"),
cl::cat(MiscOptions), cl::sub(RawSubcommand));
@@ -341,11 +364,6 @@ cl::opt<bool> DumpSectionContribs("section-contribs",
cl::cat(MiscOptions), cl::sub(RawSubcommand));
cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
cl::cat(MiscOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpSectionHeaders("section-headers",
- cl::desc("dump section headers"),
- cl::cat(MiscOptions), cl::sub(RawSubcommand));
-cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"), cl::cat(MiscOptions),
- cl::sub(RawSubcommand));
cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
cl::cat(MiscOptions), cl::sub(RawSubcommand));
@@ -403,20 +421,11 @@ cl::opt<bool> IpiStream("ipi-stream",
cl::desc("Dump the IPI Stream (Stream 5)"),
cl::sub(PdbToYamlSubcommand), cl::init(false));
-cl::list<std::string> InputFilename(cl::Positional,
- cl::desc("<input PDB file>"), cl::Required,
- cl::sub(PdbToYamlSubcommand));
-}
-
-namespace shared {
-cl::OptionCategory FileOptions("Module & File Options");
-
// MODULE & FILE OPTIONS
cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
- cl::cat(FileOptions), cl::sub(RawSubcommand),
- cl::sub(PdbToYamlSubcommand));
+ cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
- cl::cat(FileOptions), cl::sub(RawSubcommand),
+ cl::cat(FileOptions),
cl::sub(PdbToYamlSubcommand));
cl::list<ModuleSubsection> DumpModuleSubsections(
"subsections", cl::ZeroOrMore, cl::CommaSeparated,
@@ -447,11 +456,15 @@ cl::list<ModuleSubsection> DumpModuleSubsections(
clEnumValN(ModuleSubsection::Unknown, "unknown",
"Any subsection not covered by another option"),
clEnumValN(ModuleSubsection::All, "all", "All known subsections")),
- cl::cat(FileOptions), cl::sub(RawSubcommand), cl::sub(PdbToYamlSubcommand));
+ cl::cat(FileOptions), cl::sub(PdbToYamlSubcommand));
cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
- cl::cat(FileOptions), cl::sub(RawSubcommand),
+ cl::cat(FileOptions),
cl::sub(PdbToYamlSubcommand));
-} // namespace shared
+
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(PdbToYamlSubcommand));
+} // namespace pdb2yaml
namespace analyze {
cl::opt<bool> StringTable("hash-collisions", cl::desc("Find hash collisions"),
@@ -473,13 +486,6 @@ cl::opt<std::string>
static ExitOnError ExitOnErr;
-bool opts::checkModuleSubsection(opts::ModuleSubsection MS) {
- return any_of(opts::shared::DumpModuleSubsections,
- [=](opts::ModuleSubsection M) {
- return M == MS || M == opts::ModuleSubsection::All;
- });
-}
-
static void yamlToPdb(StringRef Path) {
BumpPtrAllocator Allocator;
ErrorOr<std::unique_ptr<MemoryBuffer>> ErrorOrBuffer =
@@ -511,10 +517,12 @@ static void yamlToPdb(StringRef Path) {
for (uint32_t I = 0; I < kSpecialStreamCount; ++I)
ExitOnErr(Builder.getMsfBuilder().addStream(0));
+ StringsAndChecksums Strings;
+ Strings.setStrings(std::make_shared<DebugStringTableSubsection>());
+
if (YamlObj.StringTable.hasValue()) {
- auto &Strings = Builder.getStringTableBuilder();
for (auto S : *YamlObj.StringTable)
- Strings.insert(S);
+ Strings.strings()->insert(S);
}
pdb::yaml::PdbInfoStream DefaultInfoStream;
@@ -532,8 +540,6 @@ static void yamlToPdb(StringRef Path) {
for (auto F : Info.Features)
InfoBuilder.addFeature(F);
- auto &Strings = Builder.getStringTableBuilder().getStrings();
-
const auto &Dbi = YamlObj.DbiStream.getValueOr(DefaultDbiStream);
auto &DbiBuilder = Builder.getDbiBuilder();
DbiBuilder.setAge(Dbi.Age);
@@ -557,10 +563,14 @@ static void yamlToPdb(StringRef Path) {
}
}
+ // Each module has its own checksum subsection, so scan for it every time.
+ Strings.setChecksums(nullptr);
+ CodeViewYAML::initializeStringsAndChecksums(MI.Subsections, Strings);
+
auto CodeViewSubsections = ExitOnErr(CodeViewYAML::toCodeViewSubsectionList(
Allocator, MI.Subsections, Strings));
for (auto &SS : CodeViewSubsections) {
- ModiBuilder.addDebugSubsection(std::move(SS));
+ ModiBuilder.addDebugSubsection(SS);
}
}
@@ -580,6 +590,8 @@ static void yamlToPdb(StringRef Path) {
IpiBuilder.addTypeRecord(Type.RecordData, None);
}
+ Builder.getStringTableBuilder().setStrings(*Strings.strings());
+
ExitOnErr(Builder.commit(opts::yaml2pdb::YamlPdbOutputFile));
}
@@ -604,7 +616,7 @@ static void dumpRaw(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
auto &File = loadPDB(Path, Session);
- auto O = llvm::make_unique<LLVMOutputStyle>(File);
+ auto O = llvm::make_unique<RawOutputStyle>(File);
ExitOnErr(O->dump());
}
@@ -855,6 +867,7 @@ static void mergePdbs() {
MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, ArrayRef<uint8_t> Data) {
DestIpi.addTypeRecord(Data, None);
});
+ Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
SmallString<64> OutFile(opts::merge::PdbOutputFile);
if (OutFile.empty()) {
@@ -896,49 +909,26 @@ int main(int argc_, const char *argv_[]) {
}
}
- if ((opts::RawSubcommand && opts::raw::RawAll) ||
- (opts::PdbToYamlSubcommand && opts::pdb2yaml::All)) {
- opts::shared::DumpModules = true;
- opts::shared::DumpModuleFiles = true;
- opts::shared::DumpModuleSyms = true;
- opts::shared::DumpModuleSubsections.push_back(opts::ModuleSubsection::All);
- if (llvm::is_contained(opts::shared::DumpModuleSubsections,
- opts::ModuleSubsection::All)) {
- opts::shared::DumpModuleSubsections.reset();
- opts::shared::DumpModuleSubsections.push_back(
- opts::ModuleSubsection::All);
- }
- }
-
- if (opts::shared::DumpModuleSyms || opts::shared::DumpModuleFiles)
- opts::shared::DumpModules = true;
-
- if (opts::shared::DumpModules)
- opts::pdb2yaml::DbiStream = true;
-
if (opts::RawSubcommand) {
if (opts::raw::RawAll) {
- opts::raw::DumpHeaders = true;
- opts::raw::DumpGlobals = true;
+ opts::raw::DumpLines = true;
+ opts::raw::DumpInlineeLines = true;
+ opts::raw::DumpXme = true;
+ opts::raw::DumpXmi = true;
+ opts::raw::DumpIds = true;
opts::raw::DumpPublics = true;
- opts::raw::DumpSectionHeaders = true;
- opts::raw::DumpStreamSummary = true;
- opts::raw::DumpPageStats = true;
- opts::raw::DumpStreamBlocks = true;
- opts::raw::DumpTpiRecords = true;
- opts::raw::DumpTpiHash = true;
- opts::raw::DumpIpiRecords = true;
- opts::raw::DumpSectionMap = true;
opts::raw::DumpSectionContribs = true;
- opts::raw::DumpFpo = true;
+ opts::raw::DumpSectionMap = true;
+ opts::raw::DumpStreams = true;
opts::raw::DumpStringTable = true;
- }
-
- if (opts::raw::CompactRecords &&
- (opts::raw::DumpTpiRecordBytes || opts::raw::DumpIpiRecordBytes)) {
- errs() << "-compact-records is incompatible with -tpi-record-bytes and "
- "-ipi-record-bytes.\n";
- exit(1);
+ opts::raw::DumpSummary = true;
+ opts::raw::DumpSymbols = true;
+ opts::raw::DumpIds = true;
+ opts::raw::DumpIdExtras = true;
+ opts::raw::DumpTypes = true;
+ opts::raw::DumpTypeExtras = true;
+ opts::raw::DumpModules = true;
+ opts::raw::DumpModuleFiles = true;
}
}
if (opts::PdbToYamlSubcommand) {
@@ -950,7 +940,24 @@ int main(int argc_, const char *argv_[]) {
opts::pdb2yaml::DbiStream = true;
opts::pdb2yaml::TpiStream = true;
opts::pdb2yaml::IpiStream = true;
+ opts::pdb2yaml::DumpModules = true;
+ opts::pdb2yaml::DumpModuleFiles = true;
+ opts::pdb2yaml::DumpModuleSyms = true;
+ opts::pdb2yaml::DumpModuleSubsections.push_back(
+ opts::ModuleSubsection::All);
+ if (llvm::is_contained(opts::pdb2yaml::DumpModuleSubsections,
+ opts::ModuleSubsection::All)) {
+ opts::pdb2yaml::DumpModuleSubsections.reset();
+ opts::pdb2yaml::DumpModuleSubsections.push_back(
+ opts::ModuleSubsection::All);
+ }
}
+
+ if (opts::pdb2yaml::DumpModuleSyms || opts::pdb2yaml::DumpModuleFiles)
+ opts::pdb2yaml::DumpModules = true;
+
+ if (opts::pdb2yaml::DumpModules)
+ opts::pdb2yaml::DbiStream = true;
}
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
diff --git a/tools/llvm-pdbutil/llvm-pdbutil.h b/tools/llvm-pdbutil/llvm-pdbutil.h
index f1699d0bb557..a41b032d2b13 100644
--- a/tools/llvm-pdbutil/llvm-pdbutil.h
+++ b/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -27,6 +27,8 @@ uint32_t getTypeLength(const PDBSymbolData &Symbol);
namespace opts {
+enum class DumpLevel { None, Basic, Verbose };
+
enum class ModuleSubsection {
Unknown,
Lines,
@@ -41,15 +43,6 @@ enum class ModuleSubsection {
All
};
-bool checkModuleSubsection(ModuleSubsection Kind);
-
-template <typename... Ts>
-bool checkModuleSubsection(ModuleSubsection K1, ModuleSubsection K2,
- Ts &&... Rest) {
- return checkModuleSubsection(K1) ||
- checkModuleSubsection(K2, std::forward<Ts>(Rest)...);
-}
-
namespace pretty {
enum class ClassDefinitionFormat { None, Layout, All };
@@ -105,27 +98,30 @@ struct BlockRange {
llvm::Optional<uint32_t> Max;
};
+extern llvm::cl::opt<bool> DumpSummary;
+extern llvm::cl::opt<bool> DumpStreams;
extern llvm::Optional<BlockRange> DumpBlockRange;
extern llvm::cl::list<std::string> DumpStreamData;
-extern llvm::cl::opt<bool> CompactRecords;
-extern llvm::cl::opt<bool> DumpGlobals;
-extern llvm::cl::opt<bool> DumpHeaders;
-extern llvm::cl::opt<bool> DumpStreamBlocks;
-extern llvm::cl::opt<bool> DumpStreamSummary;
-extern llvm::cl::opt<bool> DumpPageStats;
-extern llvm::cl::opt<bool> DumpTpiHash;
-extern llvm::cl::opt<bool> DumpTpiRecordBytes;
-extern llvm::cl::opt<bool> DumpTpiRecords;
-extern llvm::cl::opt<bool> DumpIpiRecords;
-extern llvm::cl::opt<bool> DumpIpiRecordBytes;
+extern llvm::cl::opt<bool> DumpLines;
+extern llvm::cl::opt<bool> DumpInlineeLines;
+extern llvm::cl::opt<bool> DumpXmi;
+extern llvm::cl::opt<bool> DumpXme;
+extern llvm::cl::opt<bool> DumpStringTable;
+extern llvm::cl::opt<bool> DumpTypes;
+extern llvm::cl::opt<bool> DumpTypeData;
+extern llvm::cl::opt<bool> DumpTypeExtras;
+extern llvm::cl::opt<bool> DumpIds;
+extern llvm::cl::opt<bool> DumpIdData;
+extern llvm::cl::opt<bool> DumpIdExtras;
+extern llvm::cl::opt<bool> DumpSymbols;
+extern llvm::cl::opt<bool> DumpSymRecordBytes;
extern llvm::cl::opt<bool> DumpPublics;
extern llvm::cl::opt<bool> DumpSectionContribs;
extern llvm::cl::opt<bool> DumpSectionMap;
-extern llvm::cl::opt<bool> DumpSymRecordBytes;
-extern llvm::cl::opt<bool> DumpSectionHeaders;
-extern llvm::cl::opt<bool> DumpFpo;
-extern llvm::cl::opt<bool> DumpStringTable;
+extern llvm::cl::opt<bool> DumpModules;
+extern llvm::cl::opt<bool> DumpModuleFiles;
+extern llvm::cl::opt<bool> RawAll;
}
namespace diff {
@@ -144,14 +140,11 @@ extern llvm::cl::opt<bool> DbiStream;
extern llvm::cl::opt<bool> TpiStream;
extern llvm::cl::opt<bool> IpiStream;
extern llvm::cl::list<std::string> InputFilename;
-}
-
-namespace shared {
extern llvm::cl::opt<bool> DumpModules;
extern llvm::cl::opt<bool> DumpModuleFiles;
extern llvm::cl::list<ModuleSubsection> DumpModuleSubsections;
extern llvm::cl::opt<bool> DumpModuleSyms;
-} // namespace shared
+} // namespace pdb2yaml
}
#endif
diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp
index 6223c09a4ded..216c9adad9a7 100644
--- a/tools/llvm-readobj/COFFDumper.cpp
+++ b/tools/llvm-readobj/COFFDumper.cpp
@@ -124,6 +124,10 @@ private:
uint32_t RelocOffset, uint32_t Offset,
StringRef *RelocSym = nullptr);
+ uint32_t countTotalTableEntries(ResourceSectionRef RSF,
+ const coff_resource_dir_table &Table,
+ StringRef Level);
+
void printResourceDirectoryTable(ResourceSectionRef RSF,
const coff_resource_dir_table &Table,
StringRef Level);
@@ -1526,6 +1530,11 @@ void COFFDumper::printCOFFResources() {
if ((Name == ".rsrc") || (Name == ".rsrc$01")) {
ResourceSectionRef RSF(Ref);
auto &BaseTable = unwrapOrError(RSF.getBaseTable());
+ W.printNumber("Total Number of Resources",
+ countTotalTableEntries(RSF, BaseTable, "Type"));
+ W.printHex("Base Table Address",
+ Obj->getCOFFSection(S)->PointerToRawData);
+ W.startLine() << "\n";
printResourceDirectoryTable(RSF, BaseTable, "Type");
}
if (opts::SectionData)
@@ -1533,15 +1542,35 @@ void COFFDumper::printCOFFResources() {
}
}
+uint32_t
+COFFDumper::countTotalTableEntries(ResourceSectionRef RSF,
+ const coff_resource_dir_table &Table,
+ StringRef Level) {
+ uint32_t TotalEntries = 0;
+ for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;
+ i++) {
+ auto Entry = unwrapOrError(getResourceDirectoryTableEntry(Table, i));
+ if (Entry.Offset.isSubDir()) {
+ StringRef NextLevel;
+ if (Level == "Name")
+ NextLevel = "Language";
+ else
+ NextLevel = "Name";
+ auto &NextTable = unwrapOrError(RSF.getEntrySubDir(Entry));
+ TotalEntries += countTotalTableEntries(RSF, NextTable, NextLevel);
+ } else {
+ TotalEntries += 1;
+ }
+ }
+ return TotalEntries;
+}
+
void COFFDumper::printResourceDirectoryTable(
ResourceSectionRef RSF, const coff_resource_dir_table &Table,
StringRef Level) {
- W.printNumber("String Name Entries", Table.NumberOfNameEntries);
- W.printNumber("ID Entries", Table.NumberOfIDEntries);
- char FormattedTime[20] = {};
- time_t TDS = time_t(Table.TimeDateStamp);
- strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
+ W.printNumber("Number of String Entries", Table.NumberOfNameEntries);
+ W.printNumber("Number of ID Entries", Table.NumberOfIDEntries);
// Iterate through level in resource directory tree.
for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;
@@ -1578,6 +1607,7 @@ void COFFDumper::printResourceDirectoryTable(
Name = StringRef(IDStr);
ListScope ResourceType(W, Level.str() + Name.str());
if (Entry.Offset.isSubDir()) {
+ W.printHex("Table Offset", Entry.Offset.value());
StringRef NextLevel;
if (Level == "Name")
NextLevel = "Language";
@@ -1586,9 +1616,14 @@ void COFFDumper::printResourceDirectoryTable(
auto &NextTable = unwrapOrError(RSF.getEntrySubDir(Entry));
printResourceDirectoryTable(RSF, NextTable, NextLevel);
} else {
+ W.printHex("Entry Offset", Entry.Offset.value());
+ char FormattedTime[20] = {};
+ time_t TDS = time_t(Table.TimeDateStamp);
+ strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
W.printHex("Time/Date Stamp", FormattedTime, Table.TimeDateStamp);
W.printNumber("Major Version", Table.MajorVersion);
W.printNumber("Minor Version", Table.MinorVersion);
+ W.printNumber("Characteristics", Table.Characteristics);
}
}
}
diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp
index 116f02f7f154..a1db96cba081 100644
--- a/tools/llvm-readobj/ELFDumper.cpp
+++ b/tools/llvm-readobj/ELFDumper.cpp
@@ -2629,6 +2629,8 @@ std::string getSectionTypeString(unsigned Arch, unsigned Type) {
return "GROUP";
case SHT_SYMTAB_SHNDX:
return "SYMTAB SECTION INDICES";
+ case SHT_LLVM_ODRTAB:
+ return "LLVM_ODRTAB";
// FIXME: Parse processor specific GNU attributes
case SHT_GNU_ATTRIBUTES:
return "ATTRIBUTES";
diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp
index f1cdc5fa1056..0ed7adb46ddc 100644
--- a/tools/llvm-stress/llvm-stress.cpp
+++ b/tools/llvm-stress/llvm-stress.cpp
@@ -382,7 +382,7 @@ struct ConstModifier: public Modifier {
switch (Ran->Rand() % 2) {
case 0: if (Ty->getScalarType()->isIntegerTy())
return PT->push_back(ConstantVector::getAllOnesValue(Ty));
- llvm_unreachable("Unexpected state");
+ break;
case 1: if (Ty->getScalarType()->isIntegerTy())
return PT->push_back(ConstantVector::getNullValue(Ty));
}
@@ -405,17 +405,15 @@ struct ConstModifier: public Modifier {
if (Ty->isIntegerTy()) {
switch (Ran->Rand() % 7) {
- case 0: if (Ty->isIntegerTy())
- return PT->push_back(ConstantInt::get(Ty,
- APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits())));
- llvm_unreachable("Unexpected state");
- case 1: if (Ty->isIntegerTy())
- return PT->push_back(ConstantInt::get(Ty,
- APInt::getNullValue(Ty->getPrimitiveSizeInBits())));
- llvm_unreachable("Unexpected state");
+ case 0:
+ return PT->push_back(ConstantInt::get(
+ Ty, APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits())));
+ case 1:
+ return PT->push_back(ConstantInt::get(
+ Ty, APInt::getNullValue(Ty->getPrimitiveSizeInBits())));
case 2: case 3: case 4: case 5:
- case 6: if (Ty->isIntegerTy())
- PT->push_back(ConstantInt::get(Ty, Ran->Rand()));
+ case 6:
+ PT->push_back(ConstantInt::get(Ty, Ran->Rand()));
}
}
diff --git a/tools/obj2yaml/CMakeLists.txt b/tools/obj2yaml/CMakeLists.txt
index ecd958d75b37..36dcfd92dfee 100644
--- a/tools/obj2yaml/CMakeLists.txt
+++ b/tools/obj2yaml/CMakeLists.txt
@@ -1,4 +1,5 @@
set(LLVM_LINK_COMPONENTS
+ DebugInfoCodeView
DebugInfoDWARF
Object
ObjectYAML
diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp
index c734601ede76..b1a06bca1a73 100644
--- a/tools/obj2yaml/coff2yaml.cpp
+++ b/tools/obj2yaml/coff2yaml.cpp
@@ -8,8 +8,13 @@
//===----------------------------------------------------------------------===//
#include "obj2yaml.h"
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/Object/COFF.h"
#include "llvm/ObjectYAML/COFFYAML.h"
+#include "llvm/ObjectYAML/CodeViewYAMLSymbols.h"
+#include "llvm/ObjectYAML/CodeViewYAMLTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/YAMLTraits.h"
@@ -99,8 +104,45 @@ void COFFDumper::dumpHeader() {
YAMLObj.Header.Characteristics = Obj.getCharacteristics();
}
+static void
+initializeFileAndStringTable(const llvm::object::COFFObjectFile &Obj,
+ codeview::StringsAndChecksumsRef &SC) {
+
+ ExitOnError Err("Invalid .debug$S section!");
+ // Iterate all .debug$S sections looking for the checksums and string table.
+ // Exit as soon as both sections are found.
+ for (const auto &S : Obj.sections()) {
+ if (SC.hasStrings() && SC.hasChecksums())
+ break;
+
+ StringRef SectionName;
+ S.getName(SectionName);
+ ArrayRef<uint8_t> sectionData;
+ if (SectionName != ".debug$S")
+ continue;
+
+ const object::coff_section *COFFSection = Obj.getCOFFSection(S);
+
+ Obj.getSectionContents(COFFSection, sectionData);
+
+ BinaryStreamReader Reader(sectionData, support::little);
+ uint32_t Magic;
+
+ Err(Reader.readInteger(Magic));
+ assert(Magic == COFF::DEBUG_SECTION_MAGIC && "Invalid .debug$S section!");
+
+ codeview::DebugSubsectionArray Subsections;
+ Err(Reader.readArray(Subsections, Reader.bytesRemaining()));
+
+ SC.initialize(Subsections);
+ }
+}
+
void COFFDumper::dumpSections(unsigned NumSections) {
std::vector<COFFYAML::Section> &YAMLSections = YAMLObj.Sections;
+ codeview::StringsAndChecksumsRef SC;
+ initializeFileAndStringTable(Obj, SC);
+
for (const auto &ObjSection : Obj.sections()) {
const object::coff_section *COFFSection = Obj.getCOFFSection(ObjSection);
COFFYAML::Section NewYAMLSection;
@@ -108,6 +150,16 @@ void COFFDumper::dumpSections(unsigned NumSections) {
NewYAMLSection.Header.Characteristics = COFFSection->Characteristics;
NewYAMLSection.Header.VirtualAddress = ObjSection.getAddress();
NewYAMLSection.Header.VirtualSize = COFFSection->VirtualSize;
+ NewYAMLSection.Header.NumberOfLineNumbers =
+ COFFSection->NumberOfLinenumbers;
+ NewYAMLSection.Header.NumberOfRelocations =
+ COFFSection->NumberOfRelocations;
+ NewYAMLSection.Header.PointerToLineNumbers =
+ COFFSection->PointerToLinenumbers;
+ NewYAMLSection.Header.PointerToRawData = COFFSection->PointerToRawData;
+ NewYAMLSection.Header.PointerToRelocations =
+ COFFSection->PointerToRelocations;
+ NewYAMLSection.Header.SizeOfRawData = COFFSection->SizeOfRawData;
NewYAMLSection.Alignment = ObjSection.getAlignment();
assert(NewYAMLSection.Alignment <= 8192);
@@ -116,6 +168,11 @@ void COFFDumper::dumpSections(unsigned NumSections) {
Obj.getSectionContents(COFFSection, sectionData);
NewYAMLSection.SectionData = yaml::BinaryRef(sectionData);
+ if (NewYAMLSection.Name == ".debug$S")
+ NewYAMLSection.DebugS = CodeViewYAML::fromDebugS(sectionData, SC);
+ else if (NewYAMLSection.Name == ".debug$T")
+ NewYAMLSection.DebugT = CodeViewYAML::fromDebugT(sectionData);
+
std::vector<COFFYAML::Relocation> Relocations;
for (const auto &Reloc : ObjSection.relocations()) {
const object::coff_relocation *reloc = Obj.getCOFFRelocation(Reloc);
diff --git a/tools/yaml2obj/CMakeLists.txt b/tools/yaml2obj/CMakeLists.txt
index a885547598d8..adeac2331a6b 100644
--- a/tools/yaml2obj/CMakeLists.txt
+++ b/tools/yaml2obj/CMakeLists.txt
@@ -1,4 +1,5 @@
set(LLVM_LINK_COMPONENTS
+ DebugInfoCodeView
MC
Object
ObjectYAML
diff --git a/tools/yaml2obj/yaml2coff.cpp b/tools/yaml2obj/yaml2coff.cpp
index 8f3f52179528..1f302fdc45a7 100644
--- a/tools/yaml2obj/yaml2coff.cpp
+++ b/tools/yaml2obj/yaml2coff.cpp
@@ -17,6 +17,8 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/Object/COFF.h"
#include "llvm/ObjectYAML/ObjectYAML.h"
#include "llvm/Support/Endian.h"
@@ -142,6 +144,8 @@ struct COFFParser {
COFFYAML::Object &Obj;
+ codeview::StringsAndChecksums StringsAndChecksums;
+ BumpPtrAllocator Allocator;
StringMap<unsigned> StringTableMap;
std::string StringTable;
uint32_t SectionTableStart;
@@ -165,6 +169,32 @@ namespace {
enum { DOSStubSize = 128 };
}
+static yaml::BinaryRef
+toDebugS(ArrayRef<CodeViewYAML::YAMLDebugSubsection> Subsections,
+ const codeview::StringsAndChecksums &SC, BumpPtrAllocator &Allocator) {
+ using namespace codeview;
+ ExitOnError Err("Error occurred writing .debug$S section");
+ auto CVSS =
+ Err(CodeViewYAML::toCodeViewSubsectionList(Allocator, Subsections, SC));
+
+ std::vector<DebugSubsectionRecordBuilder> Builders;
+ uint32_t Size = sizeof(uint32_t);
+ for (auto &SS : CVSS) {
+ DebugSubsectionRecordBuilder B(SS, CodeViewContainer::ObjectFile);
+ Size += B.calculateSerializedLength();
+ Builders.push_back(std::move(B));
+ }
+ uint8_t *Buffer = Allocator.Allocate<uint8_t>(Size);
+ MutableArrayRef<uint8_t> Output(Buffer, Size);
+ BinaryStreamWriter Writer(Output, support::little);
+
+ Err(Writer.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC));
+ for (const auto &B : Builders) {
+ Err(B.commit(Writer));
+ }
+ return {Output};
+}
+
// Take a CP and assign addresses and sizes to everything. Returns false if the
// layout is not valid to do.
static bool layoutCOFF(COFFParser &CP) {
@@ -179,8 +209,33 @@ static bool layoutCOFF(COFFParser &CP) {
uint32_t CurrentSectionDataOffset =
CP.SectionTableStart + CP.SectionTableSize;
+ for (COFFYAML::Section &S : CP.Obj.Sections) {
+ // We support specifying exactly one of SectionData or Subsections. So if
+ // there is already some SectionData, then we don't need to do any of this.
+ if (S.Name == ".debug$S" && S.SectionData.binary_size() == 0) {
+ CodeViewYAML::initializeStringsAndChecksums(S.DebugS,
+ CP.StringsAndChecksums);
+ if (CP.StringsAndChecksums.hasChecksums() &&
+ CP.StringsAndChecksums.hasStrings())
+ break;
+ }
+ }
+
// Assign each section data address consecutively.
for (COFFYAML::Section &S : CP.Obj.Sections) {
+ if (S.Name == ".debug$S") {
+ if (S.SectionData.binary_size() == 0) {
+ assert(CP.StringsAndChecksums.hasStrings() &&
+ "Object file does not have debug string table!");
+
+ S.SectionData =
+ toDebugS(S.DebugS, CP.StringsAndChecksums, CP.Allocator);
+ }
+ } else if (S.Name == ".debug$T") {
+ if (S.SectionData.binary_size() == 0)
+ S.SectionData = CodeViewYAML::toDebugT(S.DebugT, CP.Allocator);
+ }
+
if (S.SectionData.binary_size() > 0) {
CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset,
CP.isPE() ? CP.getFileAlignment() : 4);
@@ -543,6 +598,7 @@ int yaml2coff(llvm::COFFYAML::Object &Doc, raw_ostream &Out) {
errs() << "yaml2obj: Failed to layout optional header for COFF file!\n";
return 1;
}
+
if (!layoutCOFF(CP)) {
errs() << "yaml2obj: Failed to layout COFF file!\n";
return 1;
diff --git a/tools/yaml2obj/yaml2obj.cpp b/tools/yaml2obj/yaml2obj.cpp
index e64e3dc1d179..ead4b7a86b2e 100644
--- a/tools/yaml2obj/yaml2obj.cpp
+++ b/tools/yaml2obj/yaml2obj.cpp
@@ -95,5 +95,6 @@ int main(int argc, char **argv) {
if (Res == 0)
Out->keep();
+ Out->os().flush();
return Res;
}
diff --git a/unittests/ADT/SCCIteratorTest.cpp b/unittests/ADT/SCCIteratorTest.cpp
index ca6d84ed2f32..57a999bea9d5 100644
--- a/unittests/ADT/SCCIteratorTest.cpp
+++ b/unittests/ADT/SCCIteratorTest.cpp
@@ -63,8 +63,9 @@ TEST(SCCIteratorTest, AllSmallGraphs) {
// Check that every node in the SCC is reachable from every other node in
// the SCC.
for (unsigned i = 0; i != NUM_NODES; ++i)
- if (NodesInThisSCC.count(i))
+ if (NodesInThisSCC.count(i)) {
EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i)));
+ }
// OK, now that we now that every node in the SCC is reachable from every
// other, this means that the set of nodes reachable from any node in the
@@ -78,8 +79,9 @@ TEST(SCCIteratorTest, AllSmallGraphs) {
NodesReachableFromSCC.Meet(NodesInThisSCC.Complement());
for (unsigned j = 0; j != NUM_NODES; ++j)
- if (ReachableButNotInSCC.count(j))
+ if (ReachableButNotInSCC.count(j)) {
EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty());
+ }
// The result must be the same for all other nodes in this SCC, so
// there is no point in checking them.
diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp
index 5903ce8c08eb..9c501bbdf1a3 100644
--- a/unittests/ADT/SmallVectorTest.cpp
+++ b/unittests/ADT/SmallVectorTest.cpp
@@ -440,19 +440,19 @@ TYPED_TEST(SmallVectorTest, AppendNonIterTest) {
this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7);
}
+struct output_iterator {
+ typedef std::output_iterator_tag iterator_category;
+ typedef int value_type;
+ typedef int difference_type;
+ typedef value_type *pointer;
+ typedef value_type &reference;
+ operator int() { return 2; }
+ operator Constructable() { return 7; }
+};
+
TYPED_TEST(SmallVectorTest, AppendRepeatedNonForwardIterator) {
SCOPED_TRACE("AppendRepeatedTest");
- struct output_iterator {
- typedef std::output_iterator_tag iterator_category;
- typedef int value_type;
- typedef int difference_type;
- typedef value_type *pointer;
- typedef value_type &reference;
- operator int() { return 2; }
- operator Constructable() { return 7; }
- };
-
this->theVector.push_back(Constructable(1));
this->theVector.append(output_iterator(), output_iterator());
this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7);
diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp
index e308f2d7c64b..0684afe678f6 100644
--- a/unittests/ADT/StringRefTest.cpp
+++ b/unittests/ADT/StringRefTest.cpp
@@ -882,8 +882,9 @@ TEST(StringRefTest, getAsDouble) {
double Result;
StringRef S(Entry.Str);
EXPECT_EQ(Entry.ShouldFail, S.getAsDouble(Result, Entry.AllowInexact));
- if (!Entry.ShouldFail)
+ if (!Entry.ShouldFail) {
EXPECT_EQ(Result, Entry.D);
+ }
}
}
diff --git a/unittests/CodeGen/LowLevelTypeTest.cpp b/unittests/CodeGen/LowLevelTypeTest.cpp
index 428d6b93f790..115554642907 100644
--- a/unittests/CodeGen/LowLevelTypeTest.cpp
+++ b/unittests/CodeGen/LowLevelTypeTest.cpp
@@ -137,8 +137,9 @@ TEST(LowLevelTypeTest, Vector) {
if ((Elts % 2) == 0) {
EXPECT_EQ(S * (Elts / 2), HalfEltIfEvenTy.getSizeInBits());
EXPECT_EQ(S, HalfEltIfEvenTy.getScalarSizeInBits());
- if (Elts > 2)
+ if (Elts > 2) {
EXPECT_EQ(Elts / 2, HalfEltIfEvenTy.getNumElements());
+ }
}
EXPECT_EQ(S * (Elts * 2), DoubleEltTy.getSizeInBits());
diff --git a/unittests/DebugInfo/CodeView/CMakeLists.txt b/unittests/DebugInfo/CodeView/CMakeLists.txt
index 9576d45e77ba..6f504d8149b5 100644
--- a/unittests/DebugInfo/CodeView/CMakeLists.txt
+++ b/unittests/DebugInfo/CodeView/CMakeLists.txt
@@ -10,3 +10,5 @@ set(DebugInfoCodeViewSources
add_llvm_unittest(DebugInfoCodeViewTests
${DebugInfoCodeViewSources}
)
+
+target_link_libraries(DebugInfoCodeViewTests LLVMTestingSupport) \ No newline at end of file
diff --git a/unittests/DebugInfo/CodeView/ErrorChecking.h b/unittests/DebugInfo/CodeView/ErrorChecking.h
deleted file mode 100644
index 4ca74c487b3e..000000000000
--- a/unittests/DebugInfo/CodeView/ErrorChecking.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//===- ErrorChecking.h - Helpers for verifying llvm::Errors -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_UNITTESTS_DEBUGINFO_CODEVIEW_ERRORCHECKING_H
-#define LLVM_UNITTESTS_DEBUGINFO_CODEVIEW_ERRORCHECKING_H
-
-#define EXPECT_NO_ERROR(Err) \
- { \
- auto E = Err; \
- EXPECT_FALSE(static_cast<bool>(E)); \
- if (E) \
- consumeError(std::move(E)); \
- }
-
-#define EXPECT_ERROR(Err) \
- { \
- auto E = Err; \
- EXPECT_TRUE(static_cast<bool>(E)); \
- if (E) \
- consumeError(std::move(E)); \
- }
-
-#define ASSERT_EXPECTED(Exp) \
- { \
- auto E = Exp.takeError(); \
- bool Success = static_cast<bool>(E); \
- if (!Success) \
- consumeError(std::move(E)); \
- ASSERT_FALSE(Success); \
- }
-
-#define EXPECT_EXPECTED(Exp) \
- { \
- auto E = Exp.takeError(); \
- EXPECT_FALSE(static_cast<bool>(E)); \
- if (E) { \
- consumeError(std::move(E)); \
- return; \
- } \
- }
-
-#define EXPECT_EXPECTED_EQ(Val, Exp) \
- { \
- auto Result = Exp; \
- auto E = Result.takeError(); \
- EXPECT_FALSE(static_cast<bool>(E)); \
- if (E) { \
- consumeError(std::move(E)); \
- return; \
- } \
- EXPECT_EQ(Val, *Result); \
- }
-
-#define EXPECT_UNEXPECTED(Exp) \
- { \
- auto E = Exp.takeError(); \
- EXPECT_TRUE(static_cast<bool>(E)); \
- if (E) { \
- consumeError(std::move(E)); \
- return; \
- } \
- }
-
-#endif
diff --git a/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp
index 0ca24c716d1d..4fa172a37ef2 100644
--- a/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp
+++ b/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp
@@ -7,8 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "ErrorChecking.h"
-
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@@ -22,6 +20,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryItemStream.h"
#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@@ -219,7 +218,8 @@ TEST_F(RandomAccessVisitorTest, MultipleVisits) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
- EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
+ Succeeded());
}
// [0,8) should be present
@@ -247,7 +247,8 @@ TEST_F(RandomAccessVisitorTest, DescendingWithinChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
- EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
+ Succeeded());
}
// [0, 7]
@@ -275,7 +276,8 @@ TEST_F(RandomAccessVisitorTest, AscendingWithinChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
- EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
+ Succeeded());
}
// [0, 7]
@@ -305,7 +307,8 @@ TEST_F(RandomAccessVisitorTest, StopPrematurelyInChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
- EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
+ Succeeded());
}
// [0, 8) should be visited.
@@ -334,7 +337,8 @@ TEST_F(RandomAccessVisitorTest, InnerChunk) {
for (uint32_t I : IndicesToVisit) {
TypeIndex TI = TypeIndex::fromArrayIndex(I);
CVType T = Types.getType(TI);
- EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks),
+ Succeeded());
}
// [4, 9)
diff --git a/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
index 4eca7777a1e2..99c84906be9c 100644
--- a/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
+++ b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
@@ -9,7 +9,6 @@
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
-#include "ErrorChecking.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/Support/Allocator.h"
diff --git a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index 18cab52a81b0..bf004d6ffc23 100644
--- a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -311,8 +311,9 @@ void TestAllForms() {
EXPECT_EQ(Data2, toReference(DieDG.find(Attr_DW_FORM_ref2), 0));
EXPECT_EQ(Data4, toReference(DieDG.find(Attr_DW_FORM_ref4), 0));
EXPECT_EQ(Data8, toReference(DieDG.find(Attr_DW_FORM_ref8), 0));
- if (Version >= 4)
+ if (Version >= 4) {
EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0));
+ }
EXPECT_EQ(UData[0], toReference(DieDG.find(Attr_DW_FORM_ref_udata), 0));
//----------------------------------------------------------------------
@@ -320,15 +321,17 @@ void TestAllForms() {
//----------------------------------------------------------------------
EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_true), 0));
EXPECT_EQ(0ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_false), 1));
- if (Version >= 4)
+ if (Version >= 4) {
EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_present), 0));
+ }
//----------------------------------------------------------------------
// Test SLEB128 based forms
//----------------------------------------------------------------------
EXPECT_EQ(SData, toSigned(DieDG.find(Attr_DW_FORM_sdata), 0));
- if (Version >= 5)
+ if (Version >= 5) {
EXPECT_EQ(ICSData, toSigned(DieDG.find(Attr_DW_FORM_implicit_const), 0));
+ }
//----------------------------------------------------------------------
// Test ULEB128 based forms
@@ -340,9 +343,10 @@ void TestAllForms() {
//----------------------------------------------------------------------
EXPECT_EQ(Dwarf32Values[0],
toReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0));
- if (Version >= 4)
+ if (Version >= 4) {
EXPECT_EQ(Dwarf32Values[1],
toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0));
+ }
//----------------------------------------------------------------------
// Add an address at the end to make sure we can decode this value
diff --git a/unittests/DebugInfo/PDB/CMakeLists.txt b/unittests/DebugInfo/PDB/CMakeLists.txt
index cbbbd8177483..989cb396f674 100644
--- a/unittests/DebugInfo/PDB/CMakeLists.txt
+++ b/unittests/DebugInfo/PDB/CMakeLists.txt
@@ -16,3 +16,5 @@ set(DebugInfoPDBSources
add_llvm_unittest(DebugInfoPDBTests
${DebugInfoPDBSources}
)
+
+target_link_libraries(DebugInfoPDBTests LLVMTestingSupport) \ No newline at end of file
diff --git a/unittests/DebugInfo/PDB/ErrorChecking.h b/unittests/DebugInfo/PDB/ErrorChecking.h
deleted file mode 100644
index f284bfd8bb7a..000000000000
--- a/unittests/DebugInfo/PDB/ErrorChecking.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- ErrorChecking.h - Helpers for verifying llvm::Errors -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_UNITTESTS_DEBUGINFO_PDB_ERRORCHECKING_H
-#define LLVM_UNITTESTS_DEBUGINFO_PDB_ERRORCHECKING_H
-
-#define EXPECT_NO_ERROR(Err) \
- { \
- auto E = Err; \
- EXPECT_FALSE(static_cast<bool>(E)); \
- if (E) \
- consumeError(std::move(E)); \
- }
-
-#define EXPECT_ERROR(Err) \
- { \
- auto E = Err; \
- EXPECT_TRUE(static_cast<bool>(E)); \
- if (E) \
- consumeError(std::move(E)); \
- }
-
-#define EXPECT_EXPECTED(Exp) \
- { \
- auto E = Exp.takeError(); \
- EXPECT_FALSE(static_cast<bool>(E)); \
- if (E) { \
- consumeError(std::move(E)); \
- return; \
- } \
- }
-
-#define EXPECT_EXPECTED_EQ(Val, Exp) \
- { \
- auto Result = Exp; \
- auto E = Result.takeError(); \
- EXPECT_FALSE(static_cast<bool>(E)); \
- if (E) { \
- consumeError(std::move(E)); \
- return; \
- } \
- EXPECT_EQ(Val, *Result); \
- }
-
-#define EXPECT_UNEXPECTED(Exp) \
- { \
- auto E = Exp.takeError(); \
- EXPECT_TRUE(static_cast<bool>(E)); \
- if (E) { \
- consumeError(std::move(E)); \
- return; \
- } \
- }
-
-#endif
diff --git a/unittests/DebugInfo/PDB/HashTableTest.cpp b/unittests/DebugInfo/PDB/HashTableTest.cpp
index 94c9ee86c4a6..f1968e55e86f 100644
--- a/unittests/DebugInfo/PDB/HashTableTest.cpp
+++ b/unittests/DebugInfo/PDB/HashTableTest.cpp
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "ErrorChecking.h"
-#include "gtest/gtest.h"
-
#include "llvm/DebugInfo/PDB/Native/HashTable.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Testing/Support/Error.h"
+
+#include "gtest/gtest.h"
#include <vector>
@@ -150,13 +150,13 @@ TEST(HashTableTest, Serialization) {
std::vector<uint8_t> Buffer(Table.calculateSerializedLength());
MutableBinaryByteStream Stream(Buffer, little);
BinaryStreamWriter Writer(Stream);
- EXPECT_NO_ERROR(Table.commit(Writer));
+ EXPECT_THAT_ERROR(Table.commit(Writer), Succeeded());
// We should have written precisely the number of bytes we calculated earlier.
EXPECT_EQ(Buffer.size(), Writer.getOffset());
HashTableInternals Table2;
BinaryStreamReader Reader(Stream);
- EXPECT_NO_ERROR(Table2.load(Reader));
+ EXPECT_THAT_ERROR(Table2.load(Reader), Succeeded());
// We should have read precisely the number of bytes we calculated earlier.
EXPECT_EQ(Buffer.size(), Reader.getOffset());
diff --git a/unittests/DebugInfo/PDB/MSFBuilderTest.cpp b/unittests/DebugInfo/PDB/MSFBuilderTest.cpp
index 5f2f0c271e97..23a15d14f756 100644
--- a/unittests/DebugInfo/PDB/MSFBuilderTest.cpp
+++ b/unittests/DebugInfo/PDB/MSFBuilderTest.cpp
@@ -7,10 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "ErrorChecking.h"
-
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@@ -46,7 +45,7 @@ TEST_F(MSFBuilderTest, ValidateSuperBlockAccept) {
SuperBlock SB;
initializeSuperBlock(SB);
- EXPECT_NO_ERROR(msf::validateSuperBlock(SB));
+ EXPECT_THAT_ERROR(msf::validateSuperBlock(SB), Succeeded());
}
TEST_F(MSFBuilderTest, ValidateSuperBlockReject) {
@@ -56,24 +55,24 @@ TEST_F(MSFBuilderTest, ValidateSuperBlockReject) {
// Mismatched magic
SB.MagicBytes[0] = 8;
- EXPECT_ERROR(msf::validateSuperBlock(SB));
+ EXPECT_THAT_ERROR(msf::validateSuperBlock(SB), Failed());
initializeSimpleSuperBlock(SB);
// Block 0 is reserved for super block, can't be occupied by the block map
SB.BlockMapAddr = 0;
- EXPECT_ERROR(msf::validateSuperBlock(SB));
+ EXPECT_THAT_ERROR(msf::validateSuperBlock(SB), Failed());
initializeSimpleSuperBlock(SB);
// Block sizes have to be powers of 2.
SB.BlockSize = 3120;
- EXPECT_ERROR(msf::validateSuperBlock(SB));
+ EXPECT_THAT_ERROR(msf::validateSuperBlock(SB), Failed());
initializeSimpleSuperBlock(SB);
// The directory itself has a maximum size.
SB.NumDirectoryBytes = SB.BlockSize * SB.BlockSize / 4;
- EXPECT_NO_ERROR(msf::validateSuperBlock(SB));
+ EXPECT_THAT_ERROR(msf::validateSuperBlock(SB), Succeeded());
SB.NumDirectoryBytes = SB.NumDirectoryBytes + 4;
- EXPECT_ERROR(msf::validateSuperBlock(SB));
+ EXPECT_THAT_ERROR(msf::validateSuperBlock(SB), Failed());
}
TEST_F(MSFBuilderTest, TestUsedBlocksMarkedAsUsed) {
@@ -86,10 +85,11 @@ TEST_F(MSFBuilderTest, TestUsedBlocksMarkedAsUsed) {
// after the initialization.
uint32_t NumBlocks = msf::getMinimumBlockCount() + Blocks.size() + 10;
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096, NumBlocks);
- EXPECT_EXPECTED(ExpectedMsf);
+ ASSERT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
- EXPECT_EXPECTED(Msf.addStream(Blocks.size() * 4096, Blocks));
+ EXPECT_THAT_EXPECTED(Msf.addStream(Blocks.size() * 4096, Blocks),
+ Succeeded());
for (auto B : Blocks) {
EXPECT_FALSE(Msf.isBlockFree(B));
@@ -106,28 +106,28 @@ TEST_F(MSFBuilderTest, TestAddStreamNoDirectoryBlockIncrease) {
// tests the case where the directory *DOES NOT* grow large enough that it
// crosses a Block boundary.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
auto ExpectedL1 = Msf.build();
- EXPECT_EXPECTED(ExpectedL1);
+ EXPECT_THAT_EXPECTED(ExpectedL1, Succeeded());
MSFLayout &L1 = *ExpectedL1;
auto OldDirBlocks = L1.DirectoryBlocks;
EXPECT_EQ(1U, OldDirBlocks.size());
auto ExpectedMsf2 = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf2);
+ EXPECT_THAT_EXPECTED(ExpectedMsf2, Succeeded());
auto &Msf2 = *ExpectedMsf2;
- EXPECT_EXPECTED(Msf2.addStream(4000));
+ EXPECT_THAT_EXPECTED(Msf2.addStream(4000), Succeeded());
EXPECT_EQ(1U, Msf2.getNumStreams());
EXPECT_EQ(4000U, Msf2.getStreamSize(0));
auto Blocks = Msf2.getStreamBlocks(0);
EXPECT_EQ(1U, Blocks.size());
auto ExpectedL2 = Msf2.build();
- EXPECT_EXPECTED(ExpectedL2);
+ EXPECT_THAT_EXPECTED(ExpectedL2, Succeeded());
MSFLayout &L2 = *ExpectedL2;
auto NewDirBlocks = L2.DirectoryBlocks;
EXPECT_EQ(1U, NewDirBlocks.size());
@@ -140,13 +140,14 @@ TEST_F(MSFBuilderTest, TestAddStreamWithDirectoryBlockIncrease) {
// so many Blocks that need to be indexed in the directory that the directory
// crosses a Block boundary.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
- EXPECT_EXPECTED(Msf.addStream(4096 * 4096 / sizeof(uint32_t)));
+ EXPECT_THAT_EXPECTED(Msf.addStream(4096 * 4096 / sizeof(uint32_t)),
+ Succeeded());
auto ExpectedL1 = Msf.build();
- EXPECT_EXPECTED(ExpectedL1);
+ EXPECT_THAT_EXPECTED(ExpectedL1, Succeeded());
MSFLayout &L1 = *ExpectedL1;
auto DirBlocks = L1.DirectoryBlocks;
EXPECT_EQ(2U, DirBlocks.size());
@@ -156,15 +157,15 @@ TEST_F(MSFBuilderTest, TestGrowStreamNoBlockIncrease) {
// Test growing an existing stream by a value that does not affect the number
// of blocks it occupies.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
- EXPECT_EXPECTED(Msf.addStream(1024));
+ EXPECT_THAT_EXPECTED(Msf.addStream(1024), Succeeded());
EXPECT_EQ(1024U, Msf.getStreamSize(0));
auto OldStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(1U, OldStreamBlocks.size());
- EXPECT_NO_ERROR(Msf.setStreamSize(0, 2048));
+ EXPECT_THAT_ERROR(Msf.setStreamSize(0, 2048), Succeeded());
EXPECT_EQ(2048U, Msf.getStreamSize(0));
auto NewStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(1U, NewStreamBlocks.size());
@@ -178,15 +179,15 @@ TEST_F(MSFBuilderTest, TestGrowStreamWithBlockIncrease) {
// stream's
// block list.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
- EXPECT_EXPECTED(Msf.addStream(2048));
+ EXPECT_THAT_EXPECTED(Msf.addStream(2048), Succeeded());
EXPECT_EQ(2048U, Msf.getStreamSize(0));
std::vector<uint32_t> OldStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(1U, OldStreamBlocks.size());
- EXPECT_NO_ERROR(Msf.setStreamSize(0, 6144));
+ EXPECT_THAT_ERROR(Msf.setStreamSize(0, 6144), Succeeded());
EXPECT_EQ(6144U, Msf.getStreamSize(0));
std::vector<uint32_t> NewStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(2U, NewStreamBlocks.size());
@@ -199,15 +200,15 @@ TEST_F(MSFBuilderTest, TestShrinkStreamNoBlockDecrease) {
// Test that shrinking an existing stream by a value that does not affect the
// number of Blocks it occupies makes no changes to stream's block list.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
- EXPECT_EXPECTED(Msf.addStream(2048));
+ EXPECT_THAT_EXPECTED(Msf.addStream(2048), Succeeded());
EXPECT_EQ(2048U, Msf.getStreamSize(0));
std::vector<uint32_t> OldStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(1U, OldStreamBlocks.size());
- EXPECT_NO_ERROR(Msf.setStreamSize(0, 1024));
+ EXPECT_THAT_ERROR(Msf.setStreamSize(0, 1024), Succeeded());
EXPECT_EQ(1024U, Msf.getStreamSize(0));
std::vector<uint32_t> NewStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(1U, NewStreamBlocks.size());
@@ -220,15 +221,15 @@ TEST_F(MSFBuilderTest, TestShrinkStreamWithBlockDecrease) {
// causes the need to deallocate new Blocks to the stream correctly updates
// the stream's block list.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
- EXPECT_EXPECTED(Msf.addStream(6144));
+ EXPECT_THAT_EXPECTED(Msf.addStream(6144), Succeeded());
EXPECT_EQ(6144U, Msf.getStreamSize(0));
std::vector<uint32_t> OldStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(2U, OldStreamBlocks.size());
- EXPECT_NO_ERROR(Msf.setStreamSize(0, 2048));
+ EXPECT_THAT_ERROR(Msf.setStreamSize(0, 2048), Succeeded());
EXPECT_EQ(2048U, Msf.getStreamSize(0));
std::vector<uint32_t> NewStreamBlocks = Msf.getStreamBlocks(0);
EXPECT_EQ(1U, NewStreamBlocks.size());
@@ -240,20 +241,20 @@ TEST_F(MSFBuilderTest, TestRejectReusedStreamBlock) {
// Test that attempting to add a stream and assigning a block that is already
// in use by another stream fails.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
- EXPECT_EXPECTED(Msf.addStream(6144));
+ EXPECT_THAT_EXPECTED(Msf.addStream(6144), Succeeded());
std::vector<uint32_t> Blocks = {2, 3};
- EXPECT_UNEXPECTED(Msf.addStream(6144, Blocks));
+ EXPECT_THAT_EXPECTED(Msf.addStream(6144, Blocks), Failed());
}
TEST_F(MSFBuilderTest, TestBlockCountsWhenAddingStreams) {
// Test that when adding multiple streams, the number of used and free Blocks
// allocated to the MSF file are as expected.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
// one for the super block, one for the directory block map
@@ -263,7 +264,7 @@ TEST_F(MSFBuilderTest, TestBlockCountsWhenAddingStreams) {
const uint32_t StreamSizes[] = {4000, 6193, 189723};
for (int I = 0; I < 3; ++I) {
- EXPECT_EXPECTED(Msf.addStream(StreamSizes[I]));
+ EXPECT_THAT_EXPECTED(Msf.addStream(StreamSizes[I]), Succeeded());
NumUsedBlocks += bytesToBlocks(StreamSizes[I], 4096);
EXPECT_EQ(NumUsedBlocks, Msf.getNumUsedBlocks());
EXPECT_EQ(0U, Msf.getNumFreeBlocks());
@@ -274,19 +275,19 @@ TEST_F(MSFBuilderTest, BuildMsfLayout) {
// Test that we can generate an MSFLayout structure from a valid layout
// specification.
auto ExpectedMsf = MSFBuilder::create(Allocator, 4096);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
const uint32_t StreamSizes[] = {4000, 6193, 189723};
uint32_t ExpectedNumBlocks = msf::getMinimumBlockCount();
for (int I = 0; I < 3; ++I) {
- EXPECT_EXPECTED(Msf.addStream(StreamSizes[I]));
+ EXPECT_THAT_EXPECTED(Msf.addStream(StreamSizes[I]), Succeeded());
ExpectedNumBlocks += bytesToBlocks(StreamSizes[I], 4096);
}
++ExpectedNumBlocks; // The directory itself should use 1 block
auto ExpectedLayout = Msf.build();
- EXPECT_EXPECTED(ExpectedLayout);
+ EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
MSFLayout &L = *ExpectedLayout;
EXPECT_EQ(4096U, L.SB->BlockSize);
EXPECT_EQ(ExpectedNumBlocks, L.SB->NumBlocks);
@@ -305,15 +306,15 @@ TEST_F(MSFBuilderTest, BuildMsfLayout) {
TEST_F(MSFBuilderTest, UseDirectoryBlockHint) {
Expected<MSFBuilder> ExpectedMsf = MSFBuilder::create(
Allocator, 4096, msf::getMinimumBlockCount() + 1, false);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
uint32_t B = msf::getFirstUnreservedBlock();
- EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({B + 1}));
- EXPECT_EXPECTED(Msf.addStream(2048, {B + 2}));
+ EXPECT_THAT_ERROR(Msf.setDirectoryBlocksHint({B + 1}), Succeeded());
+ EXPECT_THAT_EXPECTED(Msf.addStream(2048, {B + 2}), Succeeded());
auto ExpectedLayout = Msf.build();
- EXPECT_EXPECTED(ExpectedLayout);
+ EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
MSFLayout &L = *ExpectedLayout;
EXPECT_EQ(msf::getMinimumBlockCount() + 2, L.SB->NumBlocks);
EXPECT_EQ(1U, L.DirectoryBlocks.size());
@@ -326,16 +327,16 @@ TEST_F(MSFBuilderTest, UseDirectoryBlockHint) {
TEST_F(MSFBuilderTest, DirectoryBlockHintInsufficient) {
Expected<MSFBuilder> ExpectedMsf =
MSFBuilder::create(Allocator, 4096, msf::getMinimumBlockCount() + 2);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
uint32_t B = msf::getFirstUnreservedBlock();
- EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({B + 1}));
+ EXPECT_THAT_ERROR(Msf.setDirectoryBlocksHint({B + 1}), Succeeded());
uint32_t Size = 4096 * 4096 / 4;
- EXPECT_EXPECTED(Msf.addStream(Size));
+ EXPECT_THAT_EXPECTED(Msf.addStream(Size), Succeeded());
auto ExpectedLayout = Msf.build();
- EXPECT_EXPECTED(ExpectedLayout);
+ EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
MSFLayout &L = *ExpectedLayout;
EXPECT_EQ(2U, L.DirectoryBlocks.size());
EXPECT_EQ(B + 1, L.DirectoryBlocks[0]);
@@ -344,16 +345,16 @@ TEST_F(MSFBuilderTest, DirectoryBlockHintInsufficient) {
TEST_F(MSFBuilderTest, DirectoryBlockHintOverestimated) {
Expected<MSFBuilder> ExpectedMsf =
MSFBuilder::create(Allocator, 4096, msf::getMinimumBlockCount() + 2);
- EXPECT_EXPECTED(ExpectedMsf);
+ EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
auto &Msf = *ExpectedMsf;
uint32_t B = msf::getFirstUnreservedBlock();
- EXPECT_NO_ERROR(Msf.setDirectoryBlocksHint({B + 1, B + 2}));
+ EXPECT_THAT_ERROR(Msf.setDirectoryBlocksHint({B + 1, B + 2}), Succeeded());
- EXPECT_EXPECTED(Msf.addStream(2048));
+ ASSERT_THAT_EXPECTED(Msf.addStream(2048), Succeeded());
auto ExpectedLayout = Msf.build();
- EXPECT_EXPECTED(ExpectedLayout);
+ ASSERT_THAT_EXPECTED(ExpectedLayout, Succeeded());
MSFLayout &L = *ExpectedLayout;
EXPECT_EQ(1U, L.DirectoryBlocks.size());
EXPECT_EQ(B + 1, L.DirectoryBlocks[0]);
diff --git a/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
index 789fe515b018..a9a1ee4d65b9 100644
--- a/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
+++ b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
@@ -7,16 +7,16 @@
//
//===----------------------------------------------------------------------===//
-#include "ErrorChecking.h"
-
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/DebugInfo/MSF/IMSFFile.h"
#include "llvm/DebugInfo/MSF/MSFError.h"
#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
-#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Testing/Support/Error.h"
+
#include "gtest/gtest.h"
#include <unordered_map>
@@ -95,11 +95,11 @@ TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
BinaryStreamReader R(*S);
BinaryStreamRef SR;
- EXPECT_NO_ERROR(R.readStreamRef(SR, 0U));
+ EXPECT_THAT_ERROR(R.readStreamRef(SR, 0U), Succeeded());
ArrayRef<uint8_t> Buffer;
- EXPECT_ERROR(SR.readBytes(0U, 1U, Buffer));
- EXPECT_NO_ERROR(R.readStreamRef(SR, 1U));
- EXPECT_ERROR(SR.readBytes(1U, 1U, Buffer));
+ EXPECT_THAT_ERROR(SR.readBytes(0U, 1U, Buffer), Failed());
+ EXPECT_THAT_ERROR(R.readStreamRef(SR, 1U), Succeeded());
+ EXPECT_THAT_ERROR(SR.readBytes(1U, 1U, Buffer), Failed());
}
// Tests that a read which outputs into a full destination buffer works and
@@ -111,7 +111,7 @@ TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
BinaryStreamReader R(*S);
StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
- EXPECT_NO_ERROR(R.readFixedString(Str, 1));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 1), Succeeded());
EXPECT_EQ(Str, StringRef("A"));
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
}
@@ -125,12 +125,12 @@ TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
F.Allocator);
BinaryStreamReader R(*S);
StringRef Str;
- EXPECT_NO_ERROR(R.readFixedString(Str, 2));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 2), Succeeded());
EXPECT_EQ(Str, StringRef("AB"));
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
R.setOffset(6);
- EXPECT_NO_ERROR(R.readFixedString(Str, 4));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 4), Succeeded());
EXPECT_EQ(Str, StringRef("GHIJ"));
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
}
@@ -144,7 +144,7 @@ TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
F.Allocator);
BinaryStreamReader R(*S);
StringRef Str;
- EXPECT_NO_ERROR(R.readFixedString(Str, 10));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 10), Succeeded());
EXPECT_EQ(Str, StringRef("ABCDEFGHIJ"));
EXPECT_EQ(10U, F.Allocator.getBytesAllocated());
}
@@ -159,7 +159,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
StringRef Str;
R.setOffset(10);
- EXPECT_ERROR(R.readFixedString(Str, 1));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 1), Failed());
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
}
@@ -173,7 +173,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
StringRef Str;
R.setOffset(6);
- EXPECT_ERROR(R.readFixedString(Str, 5));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 5), Failed());
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
}
@@ -186,7 +186,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
BinaryStreamReader R(*S);
StringRef Str;
- EXPECT_ERROR(R.readFixedString(Str, 11));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 11), Failed());
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
}
@@ -198,7 +198,7 @@ TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
F.Allocator);
BinaryStreamReader R(*S);
StringRef Str;
- EXPECT_NO_ERROR(R.readFixedString(Str, 1));
+ EXPECT_THAT_ERROR(R.readFixedString(Str, 1), Succeeded());
EXPECT_EQ(Str, StringRef("A"));
EXPECT_EQ(0U, F.Allocator.getBytesAllocated());
}
@@ -213,12 +213,12 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingRead) {
BinaryStreamReader R(*S);
StringRef Str1;
StringRef Str2;
- EXPECT_NO_ERROR(R.readFixedString(Str1, 7));
+ EXPECT_THAT_ERROR(R.readFixedString(Str1, 7), Succeeded());
EXPECT_EQ(Str1, StringRef("ABCDEFG"));
EXPECT_EQ(7U, F.Allocator.getBytesAllocated());
R.setOffset(2);
- EXPECT_NO_ERROR(R.readFixedString(Str2, 3));
+ EXPECT_THAT_ERROR(R.readFixedString(Str2, 3), Succeeded());
EXPECT_EQ(Str2, StringRef("CDE"));
EXPECT_EQ(Str1.data() + 2, Str2.data());
EXPECT_EQ(7U, F.Allocator.getBytesAllocated());
@@ -234,12 +234,12 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingReadFail) {
BinaryStreamReader R(*S);
StringRef Str1;
StringRef Str2;
- EXPECT_NO_ERROR(R.readFixedString(Str1, 6));
+ EXPECT_THAT_ERROR(R.readFixedString(Str1, 6), Succeeded());
EXPECT_EQ(Str1, StringRef("ABCDEF"));
EXPECT_EQ(6U, F.Allocator.getBytesAllocated());
R.setOffset(4);
- EXPECT_NO_ERROR(R.readFixedString(Str2, 4));
+ EXPECT_THAT_ERROR(R.readFixedString(Str2, 4), Succeeded());
EXPECT_EQ(Str2, StringRef("EFGH"));
EXPECT_EQ(10U, F.Allocator.getBytesAllocated());
}
@@ -257,10 +257,12 @@ TEST(MappedBlockStreamTest, WriteBeyondEndOfStream) {
F, F.Allocator);
ArrayRef<uint8_t> Buffer;
- EXPECT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(LargeBuffer)));
- EXPECT_NO_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(SmallBuffer)));
- EXPECT_NO_ERROR(S->writeBytes(7, ArrayRef<uint8_t>(SmallBuffer)));
- EXPECT_ERROR(S->writeBytes(8, ArrayRef<uint8_t>(SmallBuffer)));
+ EXPECT_THAT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(LargeBuffer)), Failed());
+ EXPECT_THAT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(SmallBuffer)),
+ Succeeded());
+ EXPECT_THAT_ERROR(S->writeBytes(7, ArrayRef<uint8_t>(SmallBuffer)),
+ Succeeded());
+ EXPECT_THAT_ERROR(S->writeBytes(8, ArrayRef<uint8_t>(SmallBuffer)), Failed());
}
TEST(MappedBlockStreamTest, TestWriteBytesNoBreakBoundary) {
@@ -270,25 +272,25 @@ TEST(MappedBlockStreamTest, TestWriteBytesNoBreakBoundary) {
F, F.Allocator);
ArrayRef<uint8_t> Buffer;
- EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer));
+ EXPECT_THAT_ERROR(S->readBytes(0, 1, Buffer), Succeeded());
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('A'));
- EXPECT_NO_ERROR(S->readBytes(9, 1, Buffer));
+ EXPECT_THAT_ERROR(S->readBytes(9, 1, Buffer), Succeeded());
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('J'));
- EXPECT_NO_ERROR(S->writeBytes(0, ArrayRef<uint8_t>('J')));
- EXPECT_NO_ERROR(S->writeBytes(9, ArrayRef<uint8_t>('A')));
+ EXPECT_THAT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>('J')), Succeeded());
+ EXPECT_THAT_ERROR(S->writeBytes(9, ArrayRef<uint8_t>('A')), Succeeded());
- EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer));
+ EXPECT_THAT_ERROR(S->readBytes(0, 1, Buffer), Succeeded());
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('J'));
- EXPECT_NO_ERROR(S->readBytes(9, 1, Buffer));
+ EXPECT_THAT_ERROR(S->readBytes(9, 1, Buffer), Succeeded());
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('A'));
- EXPECT_NO_ERROR(S->writeBytes(0, ArrayRef<uint8_t>('A')));
- EXPECT_NO_ERROR(S->writeBytes(9, ArrayRef<uint8_t>('J')));
+ EXPECT_THAT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>('A')), Succeeded());
+ EXPECT_THAT_ERROR(S->writeBytes(9, ArrayRef<uint8_t>('J')), Succeeded());
- EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer));
+ EXPECT_THAT_ERROR(S->readBytes(0, 1, Buffer), Succeeded());
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('A'));
- EXPECT_NO_ERROR(S->readBytes(9, 1, Buffer));
+ EXPECT_THAT_ERROR(S->readBytes(9, 1, Buffer), Succeeded());
EXPECT_EQ(Buffer, ArrayRef<uint8_t>('J'));
}
@@ -303,12 +305,12 @@ TEST(MappedBlockStreamTest, TestWriteBytesBreakBoundary) {
F, F.Allocator);
ArrayRef<uint8_t> Buffer;
- EXPECT_NO_ERROR(S->writeBytes(0, TestData));
+ EXPECT_THAT_ERROR(S->writeBytes(0, TestData), Succeeded());
// First just compare the memory, then compare the result of reading the
// string out.
EXPECT_EQ(ArrayRef<uint8_t>(Data), ArrayRef<uint8_t>(Expected));
- EXPECT_NO_ERROR(S->readBytes(0, 8, Buffer));
+ EXPECT_THAT_ERROR(S->readBytes(0, 8, Buffer), Succeeded());
EXPECT_EQ(Buffer, ArrayRef<uint8_t>(TestData));
}
@@ -340,8 +342,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
BinaryStreamReader Reader(*S);
BinaryStreamWriter Writer(*S);
- EXPECT_NO_ERROR(Writer.writeInteger(u16[0]));
- EXPECT_NO_ERROR(Reader.readInteger(u16[1]));
+ EXPECT_THAT_ERROR(Writer.writeInteger(u16[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readInteger(u16[1]), Succeeded());
EXPECT_EQ(u16[0], u16[1]);
EXPECT_EQ(std::vector<uint8_t>({0, 0x7A, 0xEC, 0, 0, 0, 0, 0, 0, 0}),
DataBytes);
@@ -349,8 +351,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
Reader.setOffset(0);
Writer.setOffset(0);
::memset(DataBytes.data(), 0, 10);
- EXPECT_NO_ERROR(Writer.writeInteger(u32[0]));
- EXPECT_NO_ERROR(Reader.readInteger(u32[1]));
+ EXPECT_THAT_ERROR(Writer.writeInteger(u32[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readInteger(u32[1]), Succeeded());
EXPECT_EQ(u32[0], u32[1]);
EXPECT_EQ(std::vector<uint8_t>({0x17, 0x5C, 0x50, 0, 0, 0, 0x35, 0, 0, 0}),
DataBytes);
@@ -358,8 +360,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
Reader.setOffset(0);
Writer.setOffset(0);
::memset(DataBytes.data(), 0, 10);
- EXPECT_NO_ERROR(Writer.writeEnum(Enum[0]));
- EXPECT_NO_ERROR(Reader.readEnum(Enum[1]));
+ EXPECT_THAT_ERROR(Writer.writeEnum(Enum[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readEnum(Enum[1]), Succeeded());
EXPECT_EQ(Enum[0], Enum[1]);
EXPECT_EQ(std::vector<uint8_t>({0x2C, 0x60, 0x4A, 0, 0, 0, 0, 0, 0, 0}),
DataBytes);
@@ -367,8 +369,8 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
Reader.setOffset(0);
Writer.setOffset(0);
::memset(DataBytes.data(), 0, 10);
- EXPECT_NO_ERROR(Writer.writeCString(ZStr[0]));
- EXPECT_NO_ERROR(Reader.readCString(ZStr[1]));
+ EXPECT_THAT_ERROR(Writer.writeCString(ZStr[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readCString(ZStr[1]), Succeeded());
EXPECT_EQ(ZStr[0], ZStr[1]);
EXPECT_EQ(
std::vector<uint8_t>({'r', 'e', 'Z', ' ', 'S', 't', 'o', 'r', 0, 0}),
@@ -377,8 +379,9 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
Reader.setOffset(0);
Writer.setOffset(0);
::memset(DataBytes.data(), 0, 10);
- EXPECT_NO_ERROR(Writer.writeFixedString(FStr[0]));
- EXPECT_NO_ERROR(Reader.readFixedString(FStr[1], FStr[0].size()));
+ EXPECT_THAT_ERROR(Writer.writeFixedString(FStr[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readFixedString(FStr[1], FStr[0].size()),
+ Succeeded());
EXPECT_EQ(FStr[0], FStr[1]);
EXPECT_EQ(
std::vector<uint8_t>({'x', 'i', 'F', 'd', ' ', 'S', 'e', 't', 0, 'r'}),
@@ -387,8 +390,9 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
Reader.setOffset(0);
Writer.setOffset(0);
::memset(DataBytes.data(), 0, 10);
- EXPECT_NO_ERROR(Writer.writeArray(byteArray[0]));
- EXPECT_NO_ERROR(Reader.readArray(byteArray[1], byteArray[0].size()));
+ EXPECT_THAT_ERROR(Writer.writeArray(byteArray[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readArray(byteArray[1], byteArray[0].size()),
+ Succeeded());
EXPECT_EQ(byteArray[0], byteArray[1]);
EXPECT_EQ(std::vector<uint8_t>({0, 0x32, 0x31, 0, 0, 0, 0, 0, 0, 0}),
DataBytes);
@@ -396,8 +400,9 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
Reader.setOffset(0);
Writer.setOffset(0);
::memset(DataBytes.data(), 0, 10);
- EXPECT_NO_ERROR(Writer.writeArray(intArray[0]));
- EXPECT_NO_ERROR(Reader.readArray(intArray[1], intArray[0].size()));
+ EXPECT_THAT_ERROR(Writer.writeArray(intArray[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readArray(intArray[1], intArray[0].size()),
+ Succeeded());
EXPECT_EQ(intArray[0], intArray[1]);
}
@@ -416,20 +421,20 @@ TEST(MappedBlockStreamTest, TestWriteContiguousStreamRef) {
// First write "Test Str" into the source stream.
MutableBinaryByteStream SourceStream(SrcData, little);
BinaryStreamWriter SourceWriter(SourceStream);
- EXPECT_NO_ERROR(SourceWriter.writeCString("Test Str"));
+ EXPECT_THAT_ERROR(SourceWriter.writeCString("Test Str"), Succeeded());
EXPECT_EQ(SrcDataBytes, std::vector<uint8_t>(
{'T', 'e', 's', 't', ' ', 'S', 't', 'r', 0, 0}));
// Then write the source stream into the dest stream.
BinaryStreamWriter DestWriter(*DestStream);
- EXPECT_NO_ERROR(DestWriter.writeStreamRef(SourceStream));
+ EXPECT_THAT_ERROR(DestWriter.writeStreamRef(SourceStream), Succeeded());
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
// Then read the string back out of the dest stream.
StringRef Result;
BinaryStreamReader DestReader(*DestStream);
- EXPECT_NO_ERROR(DestReader.readCString(Result));
+ EXPECT_THAT_ERROR(DestReader.readCString(Result), Succeeded());
EXPECT_EQ(Result, "Test Str");
}
@@ -452,20 +457,20 @@ TEST(MappedBlockStreamTest, TestWriteDiscontiguousStreamRef) {
// First write "Test Str" into the source stream.
BinaryStreamWriter SourceWriter(*Src);
- EXPECT_NO_ERROR(SourceWriter.writeCString("Test Str"));
+ EXPECT_THAT_ERROR(SourceWriter.writeCString("Test Str"), Succeeded());
EXPECT_EQ(SrcDataBytes, std::vector<uint8_t>(
{'e', 'T', 't', 't', ' ', 'S', 's', 'r', 0, 0}));
// Then write the source stream into the dest stream.
BinaryStreamWriter DestWriter(*Dest);
- EXPECT_NO_ERROR(DestWriter.writeStreamRef(*Src));
+ EXPECT_THAT_ERROR(DestWriter.writeStreamRef(*Src), Succeeded());
EXPECT_EQ(DestDataBytes, std::vector<uint8_t>(
{'s', 'e', 'T', ' ', 'S', 't', 't', 'r', 0, 0}));
// Then read the string back out of the dest stream.
StringRef Result;
BinaryStreamReader DestReader(*Dest);
- EXPECT_NO_ERROR(DestReader.readCString(Result));
+ EXPECT_THAT_ERROR(DestReader.readCString(Result), Succeeded());
EXPECT_EQ(Result, "Test Str");
}
@@ -484,8 +489,8 @@ TEST(MappedBlockStreamTest, DataLivesAfterStreamDestruction) {
BinaryStreamReader Reader(*S);
BinaryStreamWriter Writer(*S);
::memset(DataBytes.data(), 0, 10);
- EXPECT_NO_ERROR(Writer.writeCString(Str[0]));
- EXPECT_NO_ERROR(Reader.readCString(Str[1]));
+ EXPECT_THAT_ERROR(Writer.writeCString(Str[0]), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readCString(Str[1]), Succeeded());
EXPECT_EQ(Str[0], Str[1]);
}
diff --git a/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp b/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp
index 249bc4a03b87..0efc2c6411b8 100644
--- a/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp
+++ b/unittests/DebugInfo/PDB/StringTableBuilderTest.cpp
@@ -7,13 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#include "ErrorChecking.h"
-
#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@@ -36,21 +35,21 @@ TEST_F(StringTableBuilderTest, Simple) {
std::vector<uint8_t> Buffer(Builder.calculateSerializedSize());
MutableBinaryByteStream OutStream(Buffer, little);
BinaryStreamWriter Writer(OutStream);
- EXPECT_NO_ERROR(Builder.commit(Writer));
+ EXPECT_THAT_ERROR(Builder.commit(Writer), Succeeded());
// Reads the contents back.
BinaryByteStream InStream(Buffer, little);
BinaryStreamReader Reader(InStream);
PDBStringTable Table;
- EXPECT_NO_ERROR(Table.reload(Reader));
+ EXPECT_THAT_ERROR(Table.reload(Reader), Succeeded());
EXPECT_EQ(3U, Table.getNameCount());
EXPECT_EQ(1U, Table.getHashVersion());
- EXPECT_EXPECTED_EQ("foo", Table.getStringForID(1));
- EXPECT_EXPECTED_EQ("bar", Table.getStringForID(5));
- EXPECT_EXPECTED_EQ("baz", Table.getStringForID(9));
- EXPECT_EXPECTED_EQ(1U, Table.getIDForString("foo"));
- EXPECT_EXPECTED_EQ(5U, Table.getIDForString("bar"));
- EXPECT_EXPECTED_EQ(9U, Table.getIDForString("baz"));
+ EXPECT_THAT_EXPECTED(Table.getStringForID(1), HasValue("foo"));
+ EXPECT_THAT_EXPECTED(Table.getStringForID(5), HasValue("bar"));
+ EXPECT_THAT_EXPECTED(Table.getStringForID(9), HasValue("baz"));
+ EXPECT_THAT_EXPECTED(Table.getIDForString("foo"), HasValue(1U));
+ EXPECT_THAT_EXPECTED(Table.getIDForString("bar"), HasValue(5U));
+ EXPECT_THAT_EXPECTED(Table.getIDForString("baz"), HasValue(9U));
}
diff --git a/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp b/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp
index 1a30dad7b341..d09b9130ee27 100644
--- a/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp
+++ b/unittests/DebugInfo/PDB/TypeServerHandlerTest.cpp
@@ -7,19 +7,18 @@
//
//===----------------------------------------------------------------------===//
-#include "ErrorChecking.h"
-
+#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
-#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@@ -127,7 +126,8 @@ TEST_F(TypeServerHandlerTest, VisitRecordNoTypeServer) {
Pipeline.addCallbackToPipeline(C1);
Pipeline.addCallbackToPipeline(C2);
- EXPECT_NO_ERROR(codeview::visitTypeRecord(TypeServerRecord, Pipeline));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(TypeServerRecord, Pipeline),
+ Succeeded());
EXPECT_EQ(MockTypeVisitorCallbacks::State::VisitTypeEnd, C1.S);
EXPECT_EQ(MockTypeVisitorCallbacks::State::VisitTypeEnd, C2.S);
@@ -141,14 +141,18 @@ TEST_F(TypeServerHandlerTest, VisitRecordWithTypeServerOnce) {
MockTypeVisitorCallbacks C1;
// Our mock server returns true the first time.
- EXPECT_NO_ERROR(codeview::visitTypeRecord(
- TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(TypeServerRecord, C1,
+ codeview::VDS_BytesExternal,
+ &Handler),
+ Succeeded());
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::Ready, C1.S);
// And false the second time.
- EXPECT_NO_ERROR(codeview::visitTypeRecord(
- TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(TypeServerRecord, C1,
+ codeview::VDS_BytesExternal,
+ &Handler),
+ Succeeded());
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::VisitTypeEnd, C1.S);
}
@@ -161,13 +165,17 @@ TEST_F(TypeServerHandlerTest, VisitRecordWithTypeServerAlways) {
MockTypeVisitorCallbacks C1;
- EXPECT_NO_ERROR(codeview::visitTypeRecord(
- TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(TypeServerRecord, C1,
+ codeview::VDS_BytesExternal,
+ &Handler),
+ Succeeded());
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::Ready, C1.S);
- EXPECT_NO_ERROR(codeview::visitTypeRecord(
- TypeServerRecord, C1, codeview::VDS_BytesExternal, &Handler));
+ EXPECT_THAT_ERROR(codeview::visitTypeRecord(TypeServerRecord, C1,
+ codeview::VDS_BytesExternal,
+ &Handler),
+ Succeeded());
EXPECT_TRUE(Handler.Handled);
EXPECT_EQ(MockTypeVisitorCallbacks::State::Ready, C1.S);
}
diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp
index bcf3babf7f68..cb38b30f43e6 100644
--- a/unittests/IR/MetadataTest.cpp
+++ b/unittests/IR/MetadataTest.cpp
@@ -2042,21 +2042,23 @@ TEST_F(DIExpressionTest, isValid) {
EXPECT_TRUE(DIExpression::get(Context, None));
// Valid constructions.
- EXPECT_VALID(dwarf::DW_OP_plus, 6);
+ EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6);
+ EXPECT_VALID(dwarf::DW_OP_constu, 6, dwarf::DW_OP_plus);
EXPECT_VALID(dwarf::DW_OP_deref);
EXPECT_VALID(dwarf::DW_OP_LLVM_fragment, 3, 7);
- EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref);
- EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6);
+ EXPECT_VALID(dwarf::DW_OP_plus_uconst, 6, dwarf::DW_OP_deref);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6);
EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_LLVM_fragment, 3, 7);
- EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6,
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus_uconst, 6,
dwarf::DW_OP_LLVM_fragment, 3, 7);
// Invalid constructions.
EXPECT_INVALID(~0u);
- EXPECT_INVALID(dwarf::DW_OP_plus);
+ EXPECT_INVALID(dwarf::DW_OP_plus, 0);
+ EXPECT_INVALID(dwarf::DW_OP_plus_uconst);
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment);
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3);
- EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus, 3);
+ EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_plus_uconst, 3);
EXPECT_INVALID(dwarf::DW_OP_LLVM_fragment, 3, 7, dwarf::DW_OP_deref);
#undef EXPECT_VALID
diff --git a/unittests/IR/PatternMatch.cpp b/unittests/IR/PatternMatch.cpp
index 02ef87f5b13e..5c13ba6ecd90 100644
--- a/unittests/IR/PatternMatch.cpp
+++ b/unittests/IR/PatternMatch.cpp
@@ -91,15 +91,26 @@ TEST_F(PatternMatchTest, FloatingPointOrderedMin) {
EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
- // Test match on OGE with inverted select.
- EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ // Test inverted selects. Note, that this "inverts" the ordering, e.g.:
+ // %cmp = fcmp oge L, R
+ // %min = select %cmp R, L
+ // Given L == NaN
+ // the above is expanded to %cmp == false ==> %min = L
+ // which is true for UnordFMin, not OrdFMin, so test that:
+
+ // [OU]GE with inverted select.
+ EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
+ EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
- // Test match on OGT with inverted select.
- EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ // [OU]GT with inverted select.
+ EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
+ EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
}
@@ -130,15 +141,27 @@ TEST_F(PatternMatchTest, FloatingPointOrderedMax) {
EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
- // Test match on OLE with inverted select.
+
+ // Test inverted selects. Note, that this "inverts" the ordering, e.g.:
+ // %cmp = fcmp ole L, R
+ // %max = select %cmp, R, L
+ // Given L == NaN,
+ // the above is expanded to %cmp == false ==> %max == L
+ // which is true for UnordFMax, not OrdFMax, so test that:
+
+ // [OU]LE with inverted select.
+ EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
- .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
+ .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
- // Test match on OLT with inverted select.
+ // [OUT]LT with inverted select.
+ EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
- .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
+ .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
}
@@ -169,15 +192,26 @@ TEST_F(PatternMatchTest, FloatingPointUnorderedMin) {
EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
- // Test match on UGE with inverted select.
- EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ // Test inverted selects. Note, that this "inverts" the ordering, e.g.:
+ // %cmp = fcmp uge L, R
+ // %min = select %cmp R, L
+ // Given L == NaN
+ // the above is expanded to %cmp == true ==> %min = R
+ // which is true for OrdFMin, not UnordFMin, so test that:
+
+ // [UO]GE with inverted select.
+ EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
+ EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
- // Test match on UGT with inverted select.
- EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ // [UO]GT with inverted select.
+ EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
+ EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
}
@@ -208,15 +242,26 @@ TEST_F(PatternMatchTest, FloatingPointUnorderedMax) {
EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
- // Test match on ULE with inverted select.
- EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ // Test inverted selects. Note, that this "inverts" the ordering, e.g.:
+ // %cmp = fcmp ule L, R
+ // %max = select %cmp R, L
+ // Given L == NaN
+ // the above is expanded to %cmp == true ==> %max = R
+ // which is true for OrdFMax, not UnordFMax, so test that:
+
+ // [UO]LE with inverted select.
+ EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
+ EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
- // Test match on ULT with inverted select.
- EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ // [UO]LT with inverted select.
+ EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
.match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
+ EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
EXPECT_EQ(L, MatchL);
EXPECT_EQ(R, MatchR);
}
diff --git a/unittests/MI/LiveIntervalTest.cpp b/unittests/MI/LiveIntervalTest.cpp
index 7118a43e6d88..01dce37d9c6d 100644
--- a/unittests/MI/LiveIntervalTest.cpp
+++ b/unittests/MI/LiveIntervalTest.cpp
@@ -151,8 +151,7 @@ body: |
std::unique_ptr<MIRParser> MIR;
std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRString,
"func");
- if (!M)
- report_fatal_error("Could not parse MIR code\n");
+ ASSERT_TRUE(M);
PM.add(new TestPass(T));
diff --git a/unittests/Support/BinaryStreamTest.cpp b/unittests/Support/BinaryStreamTest.cpp
index 795c18902a9b..e257583e4b12 100644
--- a/unittests/Support/BinaryStreamTest.cpp
+++ b/unittests/Support/BinaryStreamTest.cpp
@@ -13,6 +13,8 @@
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Testing/Support/Error.h"
+
#include "gtest/gtest.h"
#include <unordered_map>
@@ -21,30 +23,6 @@
using namespace llvm;
using namespace llvm::support;
-#define EXPECT_NO_ERROR(Err) \
- { \
- auto E = Err; \
- EXPECT_FALSE(static_cast<bool>(E)); \
- if (E) \
- consumeError(std::move(E)); \
- }
-
-#define ASSERT_NO_ERROR(Err) \
- { \
- auto E = Err; \
- ASSERT_FALSE(static_cast<bool>(E)); \
- if (E) \
- consumeError(std::move(E)); \
- }
-
-#define EXPECT_ERROR(Err) \
- { \
- auto E = Err; \
- EXPECT_TRUE(static_cast<bool>(E)); \
- if (E) \
- consumeError(std::move(E)); \
- }
-
namespace {
class BrokenStream : public WritableBinaryStream {
@@ -227,13 +205,13 @@ TEST_F(BinaryStreamTest, BinaryByteStreamBounds) {
// 1. If the read fits it should work.
ASSERT_EQ(InputData.size(), Stream.Input->getLength());
- ASSERT_NO_ERROR(Stream.Input->readBytes(2, 1, Buffer));
+ ASSERT_THAT_ERROR(Stream.Input->readBytes(2, 1, Buffer), Succeeded());
EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
- ASSERT_NO_ERROR(Stream.Input->readBytes(0, 4, Buffer));
+ ASSERT_THAT_ERROR(Stream.Input->readBytes(0, 4, Buffer), Succeeded());
EXPECT_EQ(makeArrayRef(InputData).slice(0, 4), Buffer);
// 2. Reading past the bounds of the input should fail.
- EXPECT_ERROR(Stream.Input->readBytes(4, 2, Buffer));
+ EXPECT_THAT_ERROR(Stream.Input->readBytes(4, 2, Buffer), Failed());
}
}
@@ -247,31 +225,31 @@ TEST_F(BinaryStreamTest, StreamRefBounds) {
// Read 1 byte from offset 2 should work
ASSERT_EQ(InputData.size(), Ref.getLength());
- ASSERT_NO_ERROR(Ref.readBytes(2, 1, Buffer));
+ ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded());
EXPECT_EQ(makeArrayRef(InputData).slice(2, 1), Buffer);
// Reading everything from offset 2 on.
- ASSERT_NO_ERROR(Ref.readLongestContiguousChunk(2, Buffer));
+ ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
if (Stream.IsContiguous)
EXPECT_EQ(makeArrayRef(InputData).slice(2), Buffer);
else
EXPECT_FALSE(Buffer.empty());
// Reading 6 bytes from offset 0 is too big.
- EXPECT_ERROR(Ref.readBytes(0, 6, Buffer));
- EXPECT_ERROR(Ref.readLongestContiguousChunk(6, Buffer));
+ EXPECT_THAT_ERROR(Ref.readBytes(0, 6, Buffer), Failed());
+ EXPECT_THAT_ERROR(Ref.readLongestContiguousChunk(6, Buffer), Failed());
// Reading 1 byte from offset 2 after dropping 1 byte is the same as reading
// 1 byte from offset 3.
Ref = Ref.drop_front(1);
- ASSERT_NO_ERROR(Ref.readBytes(2, 1, Buffer));
+ ASSERT_THAT_ERROR(Ref.readBytes(2, 1, Buffer), Succeeded());
if (Stream.IsContiguous)
EXPECT_EQ(makeArrayRef(InputData).slice(3, 1), Buffer);
else
EXPECT_FALSE(Buffer.empty());
// Reading everything from offset 2 on after dropping 1 byte.
- ASSERT_NO_ERROR(Ref.readLongestContiguousChunk(2, Buffer));
+ ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
if (Stream.IsContiguous)
EXPECT_EQ(makeArrayRef(InputData).slice(3), Buffer);
else
@@ -280,11 +258,11 @@ TEST_F(BinaryStreamTest, StreamRefBounds) {
// Reading 2 bytes from offset 2 after dropping 2 bytes is the same as
// reading 2 bytes from offset 4, and should fail.
Ref = Ref.drop_front(1);
- EXPECT_ERROR(Ref.readBytes(2, 2, Buffer));
+ EXPECT_THAT_ERROR(Ref.readBytes(2, 2, Buffer), Failed());
// But if we read the longest contiguous chunk instead, we should still
// get the 1 byte at the end.
- ASSERT_NO_ERROR(Ref.readLongestContiguousChunk(2, Buffer));
+ ASSERT_THAT_ERROR(Ref.readLongestContiguousChunk(2, Buffer), Succeeded());
EXPECT_EQ(makeArrayRef(InputData).take_back(), Buffer);
}
}
@@ -298,27 +276,33 @@ TEST_F(BinaryStreamTest, DropOperations) {
BinaryStreamRef Original(InputData, support::little);
ASSERT_EQ(InputData.size(), Original.getLength());
- EXPECT_NO_ERROR(Original.readBytes(0, InputData.size(), Result));
+ EXPECT_THAT_ERROR(Original.readBytes(0, InputData.size(), Result),
+ Succeeded());
EXPECT_EQ(RefData, Result);
auto Dropped = Original.drop_front(2);
- EXPECT_NO_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result));
+ EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
+ Succeeded());
EXPECT_EQ(RefData.drop_front(2), Result);
Dropped = Original.drop_back(2);
- EXPECT_NO_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result));
+ EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
+ Succeeded());
EXPECT_EQ(RefData.drop_back(2), Result);
Dropped = Original.keep_front(2);
- EXPECT_NO_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result));
+ EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
+ Succeeded());
EXPECT_EQ(RefData.take_front(2), Result);
Dropped = Original.keep_back(2);
- EXPECT_NO_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result));
+ EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
+ Succeeded());
EXPECT_EQ(RefData.take_back(2), Result);
Dropped = Original.drop_symmetric(2);
- EXPECT_NO_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result));
+ EXPECT_THAT_ERROR(Dropped.readBytes(0, Dropped.getLength(), Result),
+ Succeeded());
EXPECT_EQ(RefData.drop_front(2).drop_back(2), Result);
}
@@ -341,22 +325,24 @@ TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) {
// Read everything from Offset until the end of the input data.
ArrayRef<uint8_t> Data;
- ASSERT_NO_ERROR(Stream.Input->readBytes(Offset, ExpectedSize, Data));
+ ASSERT_THAT_ERROR(Stream.Input->readBytes(Offset, ExpectedSize, Data),
+ Succeeded());
ASSERT_EQ(ExpectedSize, Data.size());
// Then write it to the destination.
- ASSERT_NO_ERROR(Stream.Output->writeBytes(0, Data));
+ ASSERT_THAT_ERROR(Stream.Output->writeBytes(0, Data), Succeeded());
// Then we read back what we wrote, it should match the corresponding
// slice of the original input data.
ArrayRef<uint8_t> Data2;
- ASSERT_NO_ERROR(Stream.Output->readBytes(Offset, ExpectedSize, Data2));
+ ASSERT_THAT_ERROR(Stream.Output->readBytes(Offset, ExpectedSize, Data2),
+ Succeeded());
EXPECT_EQ(makeArrayRef(InputData).drop_front(Offset), Data2);
}
std::vector<uint8_t> BigData = {0, 1, 2, 3, 4};
// 2. If the write is too big, it should fail.
- EXPECT_ERROR(Stream.Output->writeBytes(3, BigData));
+ EXPECT_THAT_ERROR(Stream.Output->writeBytes(3, BigData), Failed());
}
}
@@ -456,7 +442,7 @@ TEST_F(BinaryStreamTest, StreamReaderBounds) {
StringRef S;
BinaryStreamReader Reader(*Stream.Input);
EXPECT_EQ(0U, Reader.bytesRemaining());
- EXPECT_ERROR(Reader.readFixedString(S, 1));
+ EXPECT_THAT_ERROR(Reader.readFixedString(S, 1), Failed());
}
Bytes.resize(5);
@@ -465,8 +451,8 @@ TEST_F(BinaryStreamTest, StreamReaderBounds) {
StringRef S;
BinaryStreamReader Reader(*Stream.Input);
EXPECT_EQ(Bytes.size(), Reader.bytesRemaining());
- EXPECT_NO_ERROR(Reader.readFixedString(S, 5));
- EXPECT_ERROR(Reader.readFixedString(S, 6));
+ EXPECT_THAT_ERROR(Reader.readFixedString(S, 5), Succeeded());
+ EXPECT_THAT_ERROR(Reader.readFixedString(S, 6), Failed());
}
}
@@ -484,11 +470,11 @@ TEST_F(BinaryStreamTest, StreamReaderIntegers) {
for (auto &Stream : Streams) {
BinaryStreamWriter Writer(*Stream.Output);
- ASSERT_NO_ERROR(Writer.writeObject(Little));
- ASSERT_NO_ERROR(Writer.writeObject(Big));
- ASSERT_NO_ERROR(Writer.writeInteger(NS));
- ASSERT_NO_ERROR(Writer.writeInteger(NI));
- ASSERT_NO_ERROR(Writer.writeInteger(NUL));
+ ASSERT_THAT_ERROR(Writer.writeObject(Little), Succeeded());
+ ASSERT_THAT_ERROR(Writer.writeObject(Big), Succeeded());
+ ASSERT_THAT_ERROR(Writer.writeInteger(NS), Succeeded());
+ ASSERT_THAT_ERROR(Writer.writeInteger(NI), Succeeded());
+ ASSERT_THAT_ERROR(Writer.writeInteger(NUL), Succeeded());
const support::ulittle64_t *Little2;
const support::ubig32_t *Big2;
@@ -498,11 +484,11 @@ TEST_F(BinaryStreamTest, StreamReaderIntegers) {
// 1. Reading fields individually.
BinaryStreamReader Reader(*Stream.Input);
- ASSERT_NO_ERROR(Reader.readObject(Little2));
- ASSERT_NO_ERROR(Reader.readObject(Big2));
- ASSERT_NO_ERROR(Reader.readInteger(NS2));
- ASSERT_NO_ERROR(Reader.readInteger(NI2));
- ASSERT_NO_ERROR(Reader.readInteger(NUL2));
+ ASSERT_THAT_ERROR(Reader.readObject(Little2), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readObject(Big2), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readInteger(NS2), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readInteger(NI2), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readInteger(NUL2), Succeeded());
ASSERT_EQ(0U, Reader.bytesRemaining());
EXPECT_EQ(Little, *Little2);
@@ -523,13 +509,13 @@ TEST_F(BinaryStreamTest, StreamReaderIntegerArray) {
for (auto &Stream : Streams) {
BinaryStreamReader Reader(*Stream.Input);
ArrayRef<int> IntsRef;
- ASSERT_NO_ERROR(Reader.readArray(IntsRef, Ints.size()));
+ ASSERT_THAT_ERROR(Reader.readArray(IntsRef, Ints.size()), Succeeded());
ASSERT_EQ(0U, Reader.bytesRemaining());
EXPECT_EQ(makeArrayRef(Ints), IntsRef);
Reader.setOffset(0);
FixedStreamArray<int> FixedIntsRef;
- ASSERT_NO_ERROR(Reader.readArray(FixedIntsRef, Ints.size()));
+ ASSERT_THAT_ERROR(Reader.readArray(FixedIntsRef, Ints.size()), Succeeded());
ASSERT_EQ(0U, Reader.bytesRemaining());
ASSERT_EQ(Ints, std::vector<int>(FixedIntsRef.begin(), FixedIntsRef.end()));
}
@@ -545,7 +531,7 @@ TEST_F(BinaryStreamTest, StreamReaderEnum) {
for (auto &Stream : Streams) {
BinaryStreamWriter Writer(*Stream.Output);
for (auto Value : Enums)
- ASSERT_NO_ERROR(Writer.writeEnum(Value));
+ ASSERT_THAT_ERROR(Writer.writeEnum(Value), Succeeded());
BinaryStreamReader Reader(*Stream.Input);
@@ -554,7 +540,7 @@ TEST_F(BinaryStreamTest, StreamReaderEnum) {
for (size_t I = 0; I < Enums.size(); ++I) {
MyEnum Value;
- ASSERT_NO_ERROR(Reader.readEnum(Value));
+ ASSERT_THAT_ERROR(Reader.readEnum(Value), Succeeded());
EXPECT_EQ(Enums[I], Value);
}
ASSERT_EQ(0U, Reader.bytesRemaining());
@@ -587,9 +573,9 @@ TEST_F(BinaryStreamTest, StreamReaderObject) {
const Foo *FPtrOut = nullptr;
const Foo *GPtrOut = nullptr;
const Foo *HPtrOut = nullptr;
- ASSERT_NO_ERROR(Reader.readObject(FPtrOut));
- ASSERT_NO_ERROR(Reader.readObject(GPtrOut));
- ASSERT_NO_ERROR(Reader.readObject(HPtrOut));
+ ASSERT_THAT_ERROR(Reader.readObject(FPtrOut), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readObject(GPtrOut), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readObject(HPtrOut), Succeeded());
EXPECT_EQ(0U, Reader.bytesRemaining());
EXPECT_EQ(Foos[0], *FPtrOut);
EXPECT_EQ(Foos[1], *GPtrOut);
@@ -610,10 +596,10 @@ TEST_F(BinaryStreamTest, StreamReaderStrings) {
StringRef S2;
StringRef S3;
StringRef S4;
- ASSERT_NO_ERROR(Reader.readCString(S1));
- ASSERT_NO_ERROR(Reader.readCString(S2));
- ASSERT_NO_ERROR(Reader.readCString(S3));
- ASSERT_NO_ERROR(Reader.readCString(S4));
+ ASSERT_THAT_ERROR(Reader.readCString(S1), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readCString(S2), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readCString(S3), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readCString(S4), Succeeded());
ASSERT_EQ(0U, Reader.bytesRemaining());
EXPECT_EQ("One", S1);
@@ -623,14 +609,14 @@ TEST_F(BinaryStreamTest, StreamReaderStrings) {
S1 = S2 = S3 = S4 = "";
Reader.setOffset(0);
- ASSERT_NO_ERROR(Reader.readFixedString(S1, 3));
- ASSERT_NO_ERROR(Reader.skip(1));
- ASSERT_NO_ERROR(Reader.readFixedString(S2, 3));
- ASSERT_NO_ERROR(Reader.skip(1));
- ASSERT_NO_ERROR(Reader.readFixedString(S3, 5));
- ASSERT_NO_ERROR(Reader.skip(1));
- ASSERT_NO_ERROR(Reader.readFixedString(S4, 4));
- ASSERT_NO_ERROR(Reader.skip(1));
+ ASSERT_THAT_ERROR(Reader.readFixedString(S1, 3), Succeeded());
+ ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readFixedString(S2, 3), Succeeded());
+ ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readFixedString(S3, 5), Succeeded());
+ ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
+ ASSERT_THAT_ERROR(Reader.readFixedString(S4, 4), Succeeded());
+ ASSERT_THAT_ERROR(Reader.skip(1), Succeeded());
ASSERT_EQ(0U, Reader.bytesRemaining());
EXPECT_EQ("One", S1);
@@ -648,16 +634,16 @@ TEST_F(BinaryStreamTest, StreamWriterBounds) {
// 1. Can write a string that exactly fills the buffer.
EXPECT_EQ(5U, Writer.bytesRemaining());
- EXPECT_NO_ERROR(Writer.writeFixedString("abcde"));
+ EXPECT_THAT_ERROR(Writer.writeFixedString("abcde"), Succeeded());
EXPECT_EQ(0U, Writer.bytesRemaining());
// 2. Can write an empty string even when you're full
- EXPECT_NO_ERROR(Writer.writeFixedString(""));
- EXPECT_ERROR(Writer.writeFixedString("a"));
+ EXPECT_THAT_ERROR(Writer.writeFixedString(""), Succeeded());
+ EXPECT_THAT_ERROR(Writer.writeFixedString("a"), Failed());
// 3. Can't write a string that is one character too long.
Writer.setOffset(0);
- EXPECT_ERROR(Writer.writeFixedString("abcdef"));
+ EXPECT_THAT_ERROR(Writer.writeFixedString("abcdef"), Failed());
}
}
@@ -676,11 +662,12 @@ TEST_F(BinaryStreamTest, StreamWriterIntegerArrays) {
ArrayRef<int> Ints;
ArrayRef<int> Ints2;
// First read them, then write them, then read them back.
- ASSERT_NO_ERROR(Reader.readArray(Ints, SourceInts.size()));
- ASSERT_NO_ERROR(Writer.writeArray(Ints));
+ ASSERT_THAT_ERROR(Reader.readArray(Ints, SourceInts.size()), Succeeded());
+ ASSERT_THAT_ERROR(Writer.writeArray(Ints), Succeeded());
BinaryStreamReader ReaderBacker(*Stream.Output);
- ASSERT_NO_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()));
+ ASSERT_THAT_ERROR(ReaderBacker.readArray(Ints2, SourceInts.size()),
+ Succeeded());
EXPECT_EQ(makeArrayRef(SourceInts), Ints2);
}
@@ -698,12 +685,12 @@ TEST_F(BinaryStreamTest, StringWriterStrings) {
for (auto &Stream : Streams) {
BinaryStreamWriter Writer(*Stream.Output);
for (auto S : Strings)
- ASSERT_NO_ERROR(Writer.writeCString(S));
+ ASSERT_THAT_ERROR(Writer.writeCString(S), Succeeded());
std::vector<StringRef> InStrings;
BinaryStreamReader Reader(*Stream.Input);
while (!Reader.empty()) {
StringRef S;
- ASSERT_NO_ERROR(Reader.readCString(S));
+ ASSERT_THAT_ERROR(Reader.readCString(S), Succeeded());
InStrings.push_back(S);
}
EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));
@@ -748,7 +735,7 @@ TEST_F(BinaryStreamTest, BinaryItemStream) {
MutableArrayRef<uint8_t> Buffer(Ptr, sizeof(Foo));
MutableBinaryByteStream Stream(Buffer, llvm::support::big);
BinaryStreamWriter Writer(Stream);
- ASSERT_NO_ERROR(Writer.writeObject(F));
+ ASSERT_THAT_ERROR(Writer.writeObject(F), Succeeded());
Objects.push_back(BinaryItemStreamObject(Buffer));
}
@@ -758,7 +745,7 @@ TEST_F(BinaryStreamTest, BinaryItemStream) {
for (const auto &F : Foos) {
const Foo *F2;
- ASSERT_NO_ERROR(Reader.readObject(F2));
+ ASSERT_THAT_ERROR(Reader.readObject(F2), Succeeded());
EXPECT_EQ(F.X, F2->X);
EXPECT_DOUBLE_EQ(F.Y, F2->Y);
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index 098dba83197b..e2a6561089bc 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -72,6 +72,6 @@ add_llvm_unittest(SupportTests
set_source_files_properties(AlignOfTest.cpp PROPERTIES COMPILE_FLAGS -w)
# ManagedStatic.cpp uses <pthread>.
-target_link_libraries(SupportTests ${LLVM_PTHREAD_LIB})
+target_link_libraries(SupportTests LLVMTestingSupport ${LLVM_PTHREAD_LIB})
add_subdirectory(DynamicLibrary)
diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp
index 7fdd42b4feca..f9dc3930df8c 100644
--- a/unittests/Support/CommandLineTest.cpp
+++ b/unittests/Support/CommandLineTest.cpp
@@ -180,8 +180,9 @@ void testCommandLineTokenizer(ParserFunction *parse, StringRef Input,
parse(Input, Saver, Actual, /*MarkEOLs=*/false);
EXPECT_EQ(OutputSize, Actual.size());
for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
- if (I < OutputSize)
+ if (I < OutputSize) {
EXPECT_STREQ(Output[I], Actual[I]);
+ }
}
}
@@ -528,8 +529,9 @@ TEST(CommandLineTest, GetRegisteredSubcommands) {
EXPECT_FALSE(Opt1);
EXPECT_FALSE(Opt2);
for (auto *S : cl::getRegisteredSubcommands()) {
- if (*S)
+ if (*S) {
EXPECT_EQ("sc1", S->getName());
+ }
}
cl::ResetAllOptionOccurrences();
@@ -538,8 +540,9 @@ TEST(CommandLineTest, GetRegisteredSubcommands) {
EXPECT_FALSE(Opt1);
EXPECT_FALSE(Opt2);
for (auto *S : cl::getRegisteredSubcommands()) {
- if (*S)
+ if (*S) {
EXPECT_EQ("sc2", S->getName());
+ }
}
}
diff --git a/unittests/Support/DynamicLibrary/CMakeLists.txt b/unittests/Support/DynamicLibrary/CMakeLists.txt
index 2fa4bf237d40..b5844381362e 100644
--- a/unittests/Support/DynamicLibrary/CMakeLists.txt
+++ b/unittests/Support/DynamicLibrary/CMakeLists.txt
@@ -1,7 +1,9 @@
set(LLVM_LINK_COMPONENTS Support)
-add_llvm_unittest(DynamicLibraryTests DynamicLibraryTest.cpp)
+add_library(DynamicLibraryLib STATIC ExportedFuncs.cxx)
+add_llvm_unittest(DynamicLibraryTests DynamicLibraryTest.cpp)
+target_link_libraries(DynamicLibraryTests DynamicLibraryLib)
export_executable_symbols(DynamicLibraryTests)
function(dynlib_add_module NAME)
diff --git a/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp b/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
index 80a20990de18..c54e1b7eed24 100644
--- a/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
+++ b/unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
@@ -19,8 +19,6 @@
using namespace llvm;
using namespace llvm::sys;
-extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "ProcessCall"; }
-
std::string LibPath(const std::string Name = "PipSqueak") {
const std::vector<testing::internal::string>& Argvs = testing::internal::GetArgvs();
const char *Argv0 = Argvs.size() > 0 ? Argvs[0].c_str() : "DynamicLibraryTests";
diff --git a/unittests/Support/DynamicLibrary/ExportedFuncs.cxx b/unittests/Support/DynamicLibrary/ExportedFuncs.cxx
new file mode 100644
index 000000000000..97f190b0b9bc
--- /dev/null
+++ b/unittests/Support/DynamicLibrary/ExportedFuncs.cxx
@@ -0,0 +1,16 @@
+//===- llvm/unittest/Support/DynamicLibrary/DynamicLibraryLib.cpp ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PipSqueak.h"
+
+#ifndef PIPSQUEAK_TESTA_RETURN
+#define PIPSQUEAK_TESTA_RETURN "ProcessCall"
+#endif
+
+extern "C" PIPSQUEAK_EXPORT const char *TestA() { return PIPSQUEAK_TESTA_RETURN; }
diff --git a/unittests/Support/DynamicLibrary/PipSqueak.cxx b/unittests/Support/DynamicLibrary/PipSqueak.cxx
index 79cf59255a4f..375d72c0b535 100644
--- a/unittests/Support/DynamicLibrary/PipSqueak.cxx
+++ b/unittests/Support/DynamicLibrary/PipSqueak.cxx
@@ -45,4 +45,5 @@ extern "C" PIPSQUEAK_EXPORT void TestOrder(std::vector<std::string> &V) {
Glb.Vec = &V;
}
-extern "C" PIPSQUEAK_EXPORT const char *TestA() { return "LibCall"; }
+#define PIPSQUEAK_TESTA_RETURN "LibCall"
+#include "ExportedFuncs.cxx"
diff --git a/unittests/Support/DynamicLibrary/PipSqueak.h b/unittests/Support/DynamicLibrary/PipSqueak.h
index 3e4f79a9a6f4..b44c61d64dfe 100644
--- a/unittests/Support/DynamicLibrary/PipSqueak.h
+++ b/unittests/Support/DynamicLibrary/PipSqueak.h
@@ -29,4 +29,6 @@
#define PIPSQUEAK_EXPORT
#endif
+extern "C" PIPSQUEAK_EXPORT const char *TestA();
+
#endif
diff --git a/unittests/Support/FormatVariadicTest.cpp b/unittests/Support/FormatVariadicTest.cpp
index 99b90b17ae44..5387a8ae499c 100644
--- a/unittests/Support/FormatVariadicTest.cpp
+++ b/unittests/Support/FormatVariadicTest.cpp
@@ -542,6 +542,8 @@ TEST(FormatVariadicTest, Adapter) {
EXPECT_EQ(" 171 ",
formatv("{0}", fmt_align(N, AlignStyle::Center, 7)).str());
+ EXPECT_EQ("--171--",
+ formatv("{0}", fmt_align(N, AlignStyle::Center, 7, '-')).str());
EXPECT_EQ(" 171 ", formatv("{0}", fmt_pad(N, 1, 3)).str());
EXPECT_EQ("171171171171171", formatv("{0}", fmt_repeat(N, 5)).str());
diff --git a/unittests/Target/AArch64/InstSizes.cpp b/unittests/Target/AArch64/InstSizes.cpp
index c1fe7f22dc5a..f5a6d4fa67de 100644
--- a/unittests/Target/AArch64/InstSizes.cpp
+++ b/unittests/Target/AArch64/InstSizes.cpp
@@ -21,8 +21,6 @@ std::unique_ptr<TargetMachine> createTargetMachine() {
std::string Error;
const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error);
- if (!TheTarget)
- report_fatal_error("Target not registered");
return std::unique_ptr<TargetMachine>(
TheTarget->createTargetMachine(TT, CPU, FS, TargetOptions(), None,
@@ -59,24 +57,20 @@ void runChecks(
std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRString);
std::unique_ptr<MIRParser> MParser =
createMIRParser(std::move(MBuffer), Context);
- if (!MParser)
- report_fatal_error("Couldn't create MIR parser");
+ ASSERT_TRUE(MParser);
std::unique_ptr<Module> M = MParser->parseIRModule();
- if (!M)
- report_fatal_error("Couldn't parse module");
+ ASSERT_TRUE(M);
M->setTargetTriple(TM->getTargetTriple().getTriple());
M->setDataLayout(TM->createDataLayout());
MachineModuleInfo MMI(TM);
bool Res = MParser->parseMachineFunctions(*M, MMI);
- if (Res)
- report_fatal_error("Couldn't parse MIR functions");
+ ASSERT_FALSE(Res);
auto F = M->getFunction("sizes");
- if (!F)
- report_fatal_error("Couldn't find intended function");
+ ASSERT_TRUE(F != nullptr);
auto &MF = MMI.getOrCreateMachineFunction(*F);
Checks(*II, MF);
@@ -86,6 +80,7 @@ void runChecks(
TEST(InstSizes, STACKMAP) {
std::unique_ptr<TargetMachine> TM = createTargetMachine();
+ ASSERT_TRUE(TM);
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());
runChecks(TM.get(), II.get(), "", " STACKMAP 0, 16\n"
diff --git a/unittests/Transforms/Scalar/LoopPassManagerTest.cpp b/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
index dfc351c648b1..0e5780ebec47 100644
--- a/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
+++ b/unittests/Transforms/Scalar/LoopPassManagerTest.cpp
@@ -20,9 +20,20 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/SourceMgr.h"
+
+// Workaround for the gcc 7.1 bug PR80916.
+#if defined(__GNUC__) && __GNUC__ > 6
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#if defined(__GNUC__) && __GNUC__ > 6
+# pragma GCC diagnostic pop
+#endif
+
using namespace llvm;
namespace {
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 231a6ad5706b..7c41d9fad696 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -3808,9 +3808,7 @@ void CodeGenDAGPatterns::GenerateVariants() {
DepVars);
assert(!Variants.empty() && "Must create at least original variant!");
- Variants.erase(Variants.begin()); // Remove the original pattern.
-
- if (Variants.empty()) // No variants for this pattern.
+ if (Variants.size() == 1) // No additional variants for this pattern.
continue;
DEBUG(errs() << "FOUND VARIANTS OF: ";
diff --git a/utils/opt-viewer/opt-diff.py b/utils/opt-viewer/opt-diff.py
index 8c377860653e..2b5d1bbfabbe 100755
--- a/utils/opt-viewer/opt-diff.py
+++ b/utils/opt-viewer/opt-diff.py
@@ -43,7 +43,7 @@ if __name__ == '__main__':
'-j',
default=cpu_count(),
type=int,
- help='Max job count (defaults to current CPU count)')
+ help='Max job count (defaults to %(default)s, the current CPU count)')
parser.add_argument('--output', '-o', default='diff.opt.yaml')
args = parser.parse_args()
diff --git a/utils/opt-viewer/opt-stats.py b/utils/opt-viewer/opt-stats.py
index b22a052a737a..7ce935b492c5 100755
--- a/utils/opt-viewer/opt-stats.py
+++ b/utils/opt-viewer/opt-stats.py
@@ -21,7 +21,7 @@ if __name__ == '__main__':
'-j',
default=cpu_count(),
type=int,
- help='Max job count (defaults to current CPU count)')
+ help='Max job count (defaults to %(default)s, the current CPU count)')
args = parser.parse_args()
if len(args.yaml_files) == 0:
diff --git a/utils/opt-viewer/opt-viewer.py b/utils/opt-viewer/opt-viewer.py
index a14aee5f298d..5e076d86dbe9 100755
--- a/utils/opt-viewer/opt-viewer.py
+++ b/utils/opt-viewer/opt-viewer.py
@@ -208,7 +208,7 @@ if __name__ == '__main__':
'-j',
default=cpu_count(),
type=int,
- help='Max job count (defaults to current CPU count)')
+ help='Max job count (defaults to %(default)s, the current CPU count)')
parser.add_argument(
'-source-dir',
'-s',
diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh
index f5aa3ff0cd00..560220cd53f4 100755
--- a/utils/release/test-release.sh
+++ b/utils/release/test-release.sh
@@ -416,7 +416,8 @@ function test_llvmCore() {
$SandboxDir/bin/python $BuildDir/llvm.src/utils/lit/setup.py install
mkdir -p $TestSuiteBuildDir
cd $TestSuiteBuildDir
- cmake $TestSuiteSrcDir -DTEST_SUITE_LIT=$Lit
+ env CC="$c_compiler" CXX="$cxx_compiler" \
+ cmake $TestSuiteSrcDir -DTEST_SUITE_LIT=$Lit
if ! ( ${MAKE} -j $NumJobs -k check \
2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log ) ; then
deferred_error $Phase $Flavor "test suite failed"
@@ -548,6 +549,8 @@ for Flavor in $Flavors ; do
########################################################################
# Testing: Test phase 3
+ c_compiler=$llvmCore_phase3_destdir/usr/local/bin/clang
+ cxx_compiler=$llvmCore_phase3_destdir/usr/local/bin/clang++
echo "# Testing - built with clang"
test_llvmCore 3 $Flavor $llvmCore_phase3_objdir
diff --git a/utils/update_test_checks.py b/utils/update_test_checks.py
index cace9023106f..073d43d8e4da 100755
--- a/utils/update_test_checks.py
+++ b/utils/update_test_checks.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python2.7
-"""A script to generate FileCheck statements for regression tests.
+"""A script to generate FileCheck statements for 'opt' regression tests.
-This script is a utility to update LLVM opt or llc test cases with new
+This script is a utility to update LLVM opt test cases with new
FileCheck patterns. It can either update all of the tests in the file or
a single test function.
Example usage:
-$ update_test_checks.py --tool=../bin/opt test/foo.ll
+$ update_test_checks.py --opt=../bin/opt test/foo.ll
Workflow:
1. Make a compiler patch that requires updating some number of FileCheck lines
@@ -45,23 +45,11 @@ ADVERT = '; NOTE: Assertions have been autogenerated by '
SCRUB_LEADING_WHITESPACE_RE = re.compile(r'^(\s+)')
SCRUB_WHITESPACE_RE = re.compile(r'(?!^(| \w))[ \t]+', flags=re.M)
SCRUB_TRAILING_WHITESPACE_RE = re.compile(r'[ \t]+$', flags=re.M)
-SCRUB_X86_SHUFFLES_RE = (
- re.compile(
- r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = .*)$',
- flags=re.M))
-SCRUB_X86_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)')
-SCRUB_X86_RIP_RE = re.compile(r'[.\w]+\(%rip\)')
-SCRUB_X86_LCP_RE = re.compile(r'\.LCPI[0-9]+_[0-9]+')
SCRUB_KILL_COMMENT_RE = re.compile(r'^ *#+ +kill:.*\n')
SCRUB_IR_COMMENT_RE = re.compile(r'\s*;.*')
RUN_LINE_RE = re.compile('^\s*;\s*RUN:\s*(.*)$')
IR_FUNCTION_RE = re.compile('^\s*define\s+(?:internal\s+)?[^@]*@([\w-]+)\s*\(')
-LLC_FUNCTION_RE = re.compile(
- r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?'
- r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
- r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section)',
- flags=(re.M | re.S))
OPT_FUNCTION_RE = re.compile(
r'^\s*define\s+(?:internal\s+)?[^@]*@(?P<func>[\w-]+?)\s*\('
r'(\s+)?[^)]*[^{]*\{\n(?P<body>.*?)^\}$',
@@ -76,29 +64,14 @@ IR_VALUE_RE = re.compile(r'(\s+)%([\w\.]+?)([,\s\(\)]|\Z)')
# Invoke the tool that is being tested.
def invoke_tool(args, cmd_args, ir):
with open(ir) as ir_file:
- stdout = subprocess.check_output(args.tool_binary + ' ' + cmd_args,
+ stdout = subprocess.check_output(args.opt_binary + ' ' + cmd_args,
shell=True, stdin=ir_file)
# Fix line endings to unix CR style.
stdout = stdout.replace('\r\n', '\n')
return stdout
-# FIXME: Separate the x86-specific scrubbers, so this can be used for other targets.
-def scrub_asm(asm):
- # Detect shuffle asm comments and hide the operands in favor of the comments.
- asm = SCRUB_X86_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm)
- # Generically match the stack offset of a memory operand.
- asm = SCRUB_X86_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm)
- # Generically match a RIP-relative memory operand.
- asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm)
- # Generically match a LCP symbol.
- asm = SCRUB_X86_LCP_RE.sub(r'{{\.LCPI.*}}', asm)
- # Strip kill operands inserted into the asm.
- asm = SCRUB_KILL_COMMENT_RE.sub('', asm)
- return asm
-
-
-def scrub_body(body, tool_basename):
+def scrub_body(body, opt_basename):
# Scrub runs of whitespace out of the assembly, but leave the leading
# whitespace in place.
body = SCRUB_WHITESPACE_RE.sub(r' ', body)
@@ -106,22 +79,17 @@ def scrub_body(body, tool_basename):
body = string.expandtabs(body, 2)
# Strip trailing whitespace.
body = SCRUB_TRAILING_WHITESPACE_RE.sub(r'', body)
- if tool_basename == "llc":
- body = scrub_asm(body)
return body
# Build up a dictionary of all the function bodies.
-def build_function_body_dictionary(raw_tool_output, prefixes, func_dict, verbose, tool_basename):
- if tool_basename == "llc":
- func_regex = LLC_FUNCTION_RE
- else:
- func_regex = OPT_FUNCTION_RE
+def build_function_body_dictionary(raw_tool_output, prefixes, func_dict, verbose, opt_basename):
+ func_regex = OPT_FUNCTION_RE
for m in func_regex.finditer(raw_tool_output):
if not m:
continue
func = m.group('func')
- scrubbed_body = scrub_body(m.group('body'), tool_basename)
+ scrubbed_body = scrub_body(m.group('body'), opt_basename)
if func.startswith('stress'):
# We only use the last line of the function body for stress tests.
scrubbed_body = '\n'.join(scrubbed_body.splitlines()[-1:])
@@ -188,12 +156,9 @@ def genericize_check_lines(lines):
return lines
-def add_checks(output_lines, prefix_list, func_dict, func_name, tool_basename):
- # Select a label format based on the whether we're checking asm or IR.
- if tool_basename == "llc":
- check_label_format = "; %s-LABEL: %s:"
- else:
- check_label_format = "; %s-LABEL: @%s("
+def add_checks(output_lines, prefix_list, func_dict, func_name, opt_basename):
+ # Label format is based on IR string.
+ check_label_format = "; %s-LABEL: @%s("
printed_prefixes = []
for checkprefixes, _ in prefix_list:
@@ -212,8 +177,7 @@ def add_checks(output_lines, prefix_list, func_dict, func_name, tool_basename):
# For IR output, change all defs to FileCheck variables, so we're immune
# to variable naming fashions.
- if tool_basename == "opt":
- func_body = genericize_check_lines(func_body)
+ func_body = genericize_check_lines(func_body)
# This could be selectively enabled with an optional invocation argument.
# Disabled for now: better to check everything. Be safe rather than sorry.
@@ -226,20 +190,14 @@ def add_checks(output_lines, prefix_list, func_dict, func_name, tool_basename):
# output_lines.append('; %s: %s' % (checkprefix, func_body[0]))
# is_blank_line = False
- # For llc tests, there may be asm directives between the label and the
- # first checked line (most likely that first checked line is "# BB#0").
- if tool_basename == "opt":
- is_blank_line = False
- else:
- is_blank_line = True;
+ is_blank_line = False
for func_line in func_body:
if func_line.strip() == '':
is_blank_line = True
continue
# Do not waste time checking IR comments.
- if tool_basename == "opt":
- func_line = SCRUB_IR_COMMENT_RE.sub(r'', func_line)
+ func_line = SCRUB_IR_COMMENT_RE.sub(r'', func_line)
# Skip blank lines instead of checking them.
if is_blank_line == True:
@@ -275,8 +233,8 @@ def main():
parser = argparse.ArgumentParser(description=__doc__, formatter_class=RawTextHelpFormatter)
parser.add_argument('-v', '--verbose', action='store_true',
help='Show verbose output')
- parser.add_argument('--tool-binary', default='llc',
- help='The tool used to generate the test case')
+ parser.add_argument('--opt-binary', default='opt',
+ help='The opt binary used to generate the test case')
parser.add_argument(
'--function', help='The function in the test file to update')
parser.add_argument('tests', nargs='+')
@@ -284,9 +242,9 @@ def main():
autogenerated_note = (ADVERT + 'utils/' + os.path.basename(__file__))
- tool_basename = os.path.basename(args.tool_binary)
- if (tool_basename != "llc" and tool_basename != "opt"):
- print >>sys.stderr, 'ERROR: Unexpected tool name: ' + tool_basename
+ opt_basename = os.path.basename(args.opt_binary)
+ if (opt_basename != "opt"):
+ print >>sys.stderr, 'ERROR: Unexpected opt name: ' + opt_basename
sys.exit(1)
for test in args.tests:
@@ -313,15 +271,15 @@ def main():
for l in run_lines:
(tool_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split('|', 1)])
- if not tool_cmd.startswith(tool_basename + ' '):
- print >>sys.stderr, 'WARNING: Skipping non-%s RUN line: %s' % (tool_basename, l)
+ if not tool_cmd.startswith(opt_basename + ' '):
+ print >>sys.stderr, 'WARNING: Skipping non-%s RUN line: %s' % (opt_basename, l)
continue
if not filecheck_cmd.startswith('FileCheck '):
print >>sys.stderr, 'WARNING: Skipping non-FileChecked RUN line: ' + l
continue
- tool_cmd_args = tool_cmd[len(tool_basename):].strip()
+ tool_cmd_args = tool_cmd[len(opt_basename):].strip()
tool_cmd_args = tool_cmd_args.replace('< %s', '').replace('%s', '').strip()
check_prefixes = [item for m in CHECK_PREFIX_RE.finditer(filecheck_cmd)
@@ -337,13 +295,13 @@ def main():
for prefixes, _ in prefix_list:
for prefix in prefixes:
func_dict.update({prefix: dict()})
- for prefixes, tool_args in prefix_list:
+ for prefixes, opt_args in prefix_list:
if args.verbose:
- print >>sys.stderr, 'Extracted tool cmd: ' + tool_basename + ' ' + tool_args
+ print >>sys.stderr, 'Extracted opt cmd: ' + opt_basename + ' ' + opt_args
print >>sys.stderr, 'Extracted FileCheck prefixes: ' + str(prefixes)
- raw_tool_output = invoke_tool(args, tool_args, test)
- build_function_body_dictionary(raw_tool_output, prefixes, func_dict, args.verbose, tool_basename)
+ raw_tool_output = invoke_tool(args, opt_args, test)
+ build_function_body_dictionary(raw_tool_output, prefixes, func_dict, args.verbose, opt_basename)
is_in_function = False
is_in_function_start = False
@@ -364,7 +322,7 @@ def main():
continue
# Print out the various check lines here.
- output_lines = add_checks(output_lines, prefix_list, func_dict, name, tool_basename)
+ output_lines = add_checks(output_lines, prefix_list, func_dict, name, opt_basename)
is_in_function_start = False
if is_in_function: