aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-29 16:25:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-29 16:25:25 +0000
commitab44ce3d598882e51a25eb82eb7ae6308de85ae6 (patch)
tree568d786a59d49bef961dcb9bd09d422701b9da5b
parentb5630dbadf9a2a06754194387d6b0fd9962a67f1 (diff)
downloadsrc-ab44ce3d598882e51a25eb82eb7ae6308de85ae6.tar.gz
src-ab44ce3d598882e51a25eb82eb7ae6308de85ae6.zip
Vendor import of llvm trunk r304149:vendor/llvm/llvm-trunk-r304149
Notes
Notes: svn path=/vendor/llvm/dist/; revision=319140 svn path=/vendor/llvm/llvm-trunk-r304149/; revision=319141; tag=vendor/llvm/llvm-trunk-r304149
-rw-r--r--CMakeLists.txt7
-rw-r--r--docs/Benchmarking.rst87
-rw-r--r--docs/GettingStartedVS.rst4
-rw-r--r--docs/LangRef.rst471
-rw-r--r--docs/Vectorizers.rst4
-rw-r--r--docs/index.rst1
-rw-r--r--examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h6
-rw-r--r--examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h10
-rw-r--r--examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h9
-rw-r--r--examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h13
-rw-r--r--examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h14
-rw-r--r--examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp26
-rw-r--r--examples/Kaleidoscope/include/KaleidoscopeJIT.h9
-rw-r--r--include/llvm/ADT/Triple.h1
-rw-r--r--include/llvm/Analysis/InstructionSimplify.h269
-rw-r--r--include/llvm/Analysis/LoopPass.h5
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h6
-rw-r--r--include/llvm/Analysis/TargetTransformInfo.h7
-rw-r--r--include/llvm/Analysis/TargetTransformInfoImpl.h2
-rw-r--r--include/llvm/Analysis/ValueTracking.h3
-rw-r--r--include/llvm/CodeGen/AsmPrinter.h6
-rw-r--r--include/llvm/CodeGen/AtomicExpandUtils.h26
-rw-r--r--include/llvm/CodeGen/DIE.h86
-rw-r--r--include/llvm/CodeGen/FaultMaps.h35
-rw-r--r--include/llvm/CodeGen/GlobalISel/Localizer.h78
-rw-r--r--include/llvm/CodeGen/ISDOpcodes.h8
-rw-r--r--include/llvm/CodeGen/LiveInterval.h86
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h43
-rw-r--r--include/llvm/CodeGen/LiveIntervalUnion.h14
-rw-r--r--include/llvm/CodeGen/LivePhysRegs.h116
-rw-r--r--include/llvm/CodeGen/LiveRangeEdit.h80
-rw-r--r--include/llvm/CodeGen/LiveStackAnalysis.h23
-rw-r--r--include/llvm/CodeGen/MachineBasicBlock.h121
-rw-r--r--include/llvm/CodeGen/MachineBlockFrequencyInfo.h17
-rw-r--r--include/llvm/CodeGen/MachineDominanceFrontier.h23
-rw-r--r--include/llvm/CodeGen/MachineDominators.h18
-rw-r--r--include/llvm/CodeGen/MachineInstr.h35
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h5
-rw-r--r--include/llvm/CodeGen/MachineValueType.h2
-rw-r--r--include/llvm/CodeGen/ScheduleDAG.h6
-rw-r--r--include/llvm/CodeGen/ScheduleDAGInstrs.h5
-rw-r--r--include/llvm/CodeGen/SelectionDAG.h5
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h26
-rw-r--r--include/llvm/DebugInfo/CodeView/CVRecord.h8
-rw-r--r--include/llvm/DebugInfo/CodeView/CVTypeVisitor.h1
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDeserializer.h11
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h33
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecord.h11
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeSerializer.h37
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeStreamMerger.h69
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableBuilder.h31
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableCollection.h4
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h18
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h3
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDie.h3
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFFormValue.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFRelocMap.h3
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h12
-rw-r--r--include/llvm/DebugInfo/MSF/MappedBlockStream.h16
-rw-r--r--include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h1
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h5
-rw-r--r--include/llvm/DebugInfo/PDB/Native/TpiStream.h7
-rw-r--r--include/llvm/IR/Attributes.h46
-rw-r--r--include/llvm/IR/BasicBlock.h45
-rw-r--r--include/llvm/IR/IntrinsicInst.h13
-rw-r--r--include/llvm/IR/Intrinsics.td58
-rw-r--r--include/llvm/IR/IntrinsicsAMDGPU.td10
-rw-r--r--include/llvm/IR/Metadata.h1
-rw-r--r--include/llvm/IR/Module.h5
-rw-r--r--include/llvm/InitializePasses.h2
-rw-r--r--include/llvm/LTO/Config.h2
-rw-r--r--include/llvm/Object/Binary.h4
-rw-r--r--include/llvm/Object/COFF.h1
-rw-r--r--include/llvm/Object/ELFObjectFile.h12
-rw-r--r--include/llvm/Object/MachO.h1
-rw-r--r--include/llvm/Object/ObjectFile.h6
-rw-r--r--include/llvm/Object/RelocVisitor.h513
-rw-r--r--include/llvm/Object/Wasm.h1
-rw-r--r--include/llvm/Option/OptTable.h8
-rw-r--r--include/llvm/ProfileData/InstrProf.h6
-rw-r--r--include/llvm/TableGen/Record.h48
-rw-r--r--include/llvm/Target/TargetLowering.h6
-rw-r--r--include/llvm/Transforms/Scalar.h7
-rw-r--r--include/llvm/Transforms/Scalar/GVN.h34
-rw-r--r--include/llvm/Transforms/Utils/Local.h12
-rw-r--r--lib/Analysis/ConstantFolding.cpp7
-rw-r--r--lib/Analysis/InstructionSimplify.cpp152
-rw-r--r--lib/Analysis/Lint.cpp8
-rw-r--r--lib/Analysis/LoopPass.cpp23
-rw-r--r--lib/Analysis/ScalarEvolution.cpp74
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp20
-rw-r--r--lib/Analysis/TargetTransformInfo.cpp4
-rw-r--r--lib/Analysis/ValueTracking.cpp6
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp34
-rw-r--r--lib/Bitcode/Writer/ValueEnumerator.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp10
-rw-r--r--lib/CodeGen/AsmPrinter/CodeViewDebug.cpp8
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.cpp120
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.h55
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHashAttributes.def55
-rw-r--r--lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp9
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp8
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.h4
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp125
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h9
-rw-r--r--lib/CodeGen/AtomicExpandPass.cpp2
-rw-r--r--lib/CodeGen/BasicTargetTransformInfo.cpp2
-rw-r--r--lib/CodeGen/BranchCoalescing.cpp6
-rw-r--r--lib/CodeGen/BranchFolding.cpp11
-rw-r--r--lib/CodeGen/BranchFolding.h1
-rw-r--r--lib/CodeGen/BranchRelaxation.cpp6
-rw-r--r--lib/CodeGen/CodeGenPrepare.cpp4
-rw-r--r--lib/CodeGen/DeadMachineInstructionElim.cpp4
-rw-r--r--lib/CodeGen/DetectDeadLanes.cpp3
-rw-r--r--lib/CodeGen/DwarfEHPrepare.cpp4
-rw-r--r--lib/CodeGen/EarlyIfConversion.cpp8
-rw-r--r--lib/CodeGen/ExpandISelPseudos.cpp2
-rw-r--r--lib/CodeGen/ExpandPostRAPseudos.cpp2
-rw-r--r--lib/CodeGen/FuncletLayout.cpp2
-rw-r--r--lib/CodeGen/GlobalISel/CMakeLists.txt5
-rw-r--r--lib/CodeGen/GlobalISel/GlobalISel.cpp1
-rw-r--r--lib/CodeGen/GlobalISel/Localizer.cpp125
-rw-r--r--lib/CodeGen/GlobalMerge.cpp5
-rw-r--r--lib/CodeGen/IfConversion.cpp33
-rw-r--r--lib/CodeGen/ImplicitNullChecks.cpp4
-rw-r--r--lib/CodeGen/InterleavedAccessPass.cpp6
-rw-r--r--lib/CodeGen/LexicalScopes.cpp5
-rw-r--r--lib/CodeGen/LiveDebugValues.cpp4
-rw-r--r--lib/CodeGen/LiveDebugVariables.cpp6
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp49
-rw-r--r--lib/CodeGen/LivePhysRegs.cpp89
-rw-r--r--lib/CodeGen/LiveStackAnalysis.cpp4
-rw-r--r--lib/CodeGen/LocalStackSlotAllocation.cpp4
-rw-r--r--lib/CodeGen/LowerEmuTLS.cpp2
-rw-r--r--lib/CodeGen/MachineBlockFrequencyInfo.cpp6
-rw-r--r--lib/CodeGen/MachineBlockPlacement.cpp4
-rw-r--r--lib/CodeGen/MachineCSE.cpp12
-rw-r--r--lib/CodeGen/MachineCombiner.cpp4
-rw-r--r--lib/CodeGen/MachineCopyPropagation.cpp4
-rw-r--r--lib/CodeGen/MachineLICM.cpp10
-rw-r--r--lib/CodeGen/MachineOutliner.cpp2
-rw-r--r--lib/CodeGen/MachinePipeliner.cpp4
-rw-r--r--lib/CodeGen/MachineScheduler.cpp14
-rw-r--r--lib/CodeGen/MachineSink.cpp8
-rw-r--r--lib/CodeGen/MachineTraceMetrics.cpp8
-rw-r--r--lib/CodeGen/MachineVerifier.cpp5
-rw-r--r--lib/CodeGen/OptimizePHIs.cpp4
-rw-r--r--lib/CodeGen/PHIElimination.cpp4
-rw-r--r--lib/CodeGen/PostRASchedulerList.cpp4
-rw-r--r--lib/CodeGen/ProcessImplicitDefs.cpp6
-rw-r--r--lib/CodeGen/PrologEpilogInserter.cpp9
-rw-r--r--lib/CodeGen/RenameIndependentSubregs.cpp4
-rw-r--r--lib/CodeGen/SafeStack.cpp6
-rw-r--r--lib/CodeGen/ScalarizeMaskedMemIntrin.cpp8
-rw-r--r--lib/CodeGen/ScheduleDAGInstrs.cpp206
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp176
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp67
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp81
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp90
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h2
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp55
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp34
-rw-r--r--lib/CodeGen/ShadowStackGCLowering.cpp6
-rw-r--r--lib/CodeGen/ShrinkWrap.cpp5
-rw-r--r--lib/CodeGen/SjLjEHPrepare.cpp2
-rw-r--r--lib/CodeGen/SlotIndexes.cpp2
-rw-r--r--lib/CodeGen/SpillPlacement.cpp6
-rw-r--r--lib/CodeGen/StackColoring.cpp10
-rw-r--r--lib/CodeGen/StackProtector.cpp4
-rw-r--r--lib/CodeGen/StackSlotColoring.cpp6
-rw-r--r--lib/CodeGen/TailDuplication.cpp3
-rw-r--r--lib/CodeGen/TailDuplicator.cpp4
-rw-r--r--lib/CodeGen/TwoAddressInstructionPass.cpp6
-rw-r--r--lib/CodeGen/WinEHPrepare.cpp2
-rw-r--r--lib/DebugInfo/CodeView/CMakeLists.txt1
-rw-r--r--lib/DebugInfo/CodeView/CVTypeVisitor.cpp20
-rw-r--r--lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp371
-rw-r--r--lib/DebugInfo/CodeView/TypeSerializer.cpp230
-rw-r--r--lib/DebugInfo/CodeView/TypeStreamMerger.cpp428
-rw-r--r--lib/DebugInfo/CodeView/TypeTableCollection.cpp3
-rw-r--r--lib/DebugInfo/DWARF/DWARFContext.cpp119
-rw-r--r--lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp8
-rw-r--r--lib/DebugInfo/DWARF/DWARFDie.cpp13
-rw-r--r--lib/DebugInfo/DWARF/DWARFFormValue.cpp4
-rw-r--r--lib/DebugInfo/DWARF/DWARFUnit.cpp39
-rw-r--r--lib/DebugInfo/MSF/MappedBlockStream.cpp32
-rw-r--r--lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp25
-rw-r--r--lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp19
-rw-r--r--lib/DebugInfo/PDB/Native/TpiStream.cpp4
-rw-r--r--lib/Demangle/ItaniumDemangle.cpp54
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp37
-rw-r--r--lib/Fuzzer/FuzzerUtilPosix.cpp17
-rw-r--r--lib/Fuzzer/test/fuzzer-segv.test2
-rw-r--r--lib/IR/AttributeImpl.h47
-rw-r--r--lib/IR/Attributes.cpp396
-rw-r--r--lib/IR/BasicBlock.cpp16
-rw-r--r--lib/IR/DebugLoc.cpp2
-rw-r--r--lib/IR/Instructions.cpp6
-rw-r--r--lib/IR/IntrinsicInst.cpp26
-rw-r--r--lib/IR/Module.cpp4
-rw-r--r--lib/IR/Verifier.cpp40
-rw-r--r--lib/LTO/LTO.cpp44
-rw-r--r--lib/LTO/LTOBackend.cpp21
-rw-r--r--lib/Linker/IRMover.cpp17
-rw-r--r--lib/MC/WasmObjectWriter.cpp34
-rw-r--r--lib/Object/COFFObjectFile.cpp4
-rw-r--r--lib/Object/MachOObjectFile.cpp4
-rw-r--r--lib/Object/WasmObjectFile.cpp4
-rw-r--r--lib/Option/OptTable.cpp14
-rw-r--r--lib/Passes/PassBuilder.cpp25
-rw-r--r--lib/ProfileData/InstrProf.cpp16
-rw-r--r--lib/Support/APInt.cpp4
-rw-r--r--lib/Support/BinaryStreamReader.cpp27
-rw-r--r--lib/Support/ConvertUTF.cpp31
-rw-r--r--lib/Support/DebugCounter.cpp2
-rw-r--r--lib/Support/DynamicLibrary.cpp11
-rw-r--r--lib/Support/GraphWriter.cpp1
-rw-r--r--lib/Support/Host.cpp1
-rw-r--r--lib/Support/Path.cpp1
-rw-r--r--lib/Support/Triple.cpp17
-rw-r--r--lib/Support/YAMLParser.cpp4
-rw-r--r--lib/TableGen/Record.cpp39
-rw-r--r--lib/Target/AArch64/AArch64AsmPrinter.cpp5
-rw-r--r--lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp119
-rw-r--r--lib/Target/AArch64/AArch64FrameLowering.cpp11
-rw-r--r--lib/Target/AArch64/AArch64ISelLowering.cpp31
-rw-r--r--lib/Target/AArch64/AArch64InstrInfo.cpp127
-rw-r--r--lib/Target/AArch64/AArch64InstrInfo.h2
-rw-r--r--lib/Target/AArch64/AArch64InstrInfo.td2
-rw-r--r--lib/Target/AArch64/AArch64MacroFusion.cpp13
-rw-r--r--lib/Target/AArch64/AArch64SchedFalkor.td86
-rw-r--r--lib/Target/AArch64/AArch64SchedFalkorDetails.td1109
-rw-r--r--lib/Target/AArch64/AArch64SchedFalkorWriteRes.td403
-rw-r--r--lib/Target/AArch64/AArch64Subtarget.cpp1
-rw-r--r--lib/Target/AArch64/AArch64TargetMachine.cpp12
-rw-r--r--lib/Target/AMDGPU/AMDGPU.td20
-rw-r--r--lib/Target/AMDGPU/AMDGPUISelLowering.cpp45
-rw-r--r--lib/Target/AMDGPU/AMDGPUISelLowering.h3
-rw-r--r--lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp2
-rw-r--r--lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp213
-rw-r--r--lib/Target/AMDGPU/AMDGPUSubtarget.h8
-rw-r--r--lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp83
-rw-r--r--lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp93
-rw-r--r--lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h5
-rw-r--r--lib/Target/AMDGPU/GCNIterativeScheduler.cpp2
-rw-r--r--lib/Target/AMDGPU/GCNMinRegStrategy.cpp2
-rw-r--r--lib/Target/AMDGPU/GCNRegPressure.cpp6
-rw-r--r--lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h12
-rw-r--r--lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp46
-rw-r--r--lib/Target/AMDGPU/R600ISelLowering.cpp8
-rw-r--r--lib/Target/AMDGPU/R600ISelLowering.h2
-rw-r--r--lib/Target/AMDGPU/R600RegisterInfo.td2
-rw-r--r--lib/Target/AMDGPU/SIDefines.h19
-rw-r--r--lib/Target/AMDGPU/SIISelLowering.cpp52
-rw-r--r--lib/Target/AMDGPU/SIISelLowering.h2
-rw-r--r--lib/Target/AMDGPU/SIInstrInfo.cpp4
-rw-r--r--lib/Target/AMDGPU/SIInstrInfo.td180
-rw-r--r--lib/Target/AMDGPU/SOPInstructions.td4
-rw-r--r--lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp11
-rw-r--r--lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h4
-rw-r--r--lib/Target/AMDGPU/VOP1Instructions.td33
-rw-r--r--lib/Target/AMDGPU/VOP2Instructions.td70
-rw-r--r--lib/Target/AMDGPU/VOP3Instructions.td9
-rw-r--r--lib/Target/AMDGPU/VOPCInstructions.td37
-rw-r--r--lib/Target/AMDGPU/VOPInstructions.td114
-rw-r--r--lib/Target/ARM/ARMCallLowering.cpp111
-rw-r--r--lib/Target/ARM/ARMCallLowering.h5
-rw-r--r--lib/Target/ARM/ARMExpandPseudoInsts.cpp4
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp8
-rw-r--r--lib/Target/ARM/ARMISelLowering.h2
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td496
-rw-r--r--lib/Target/ARM/ARMSchedule.td11
-rw-r--r--lib/Target/ARM/ARMScheduleA9.td9
-rw-r--r--lib/Target/ARM/ARMScheduleR52.td103
-rw-r--r--lib/Target/ARM/ARMScheduleSwift.td10
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp63
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h62
-rw-r--r--lib/Target/ARM/ARMTargetObjectFile.cpp4
-rw-r--r--lib/Target/ARM/Thumb1FrameLowering.cpp10
-rw-r--r--lib/Target/AVR/AVRInstrInfo.td1
-rw-r--r--lib/Target/BPF/BPFISelLowering.cpp9
-rw-r--r--lib/Target/BPF/BPFISelLowering.h4
-rw-r--r--lib/Target/Hexagon/HexagonFrameLowering.cpp2
-rw-r--r--lib/Target/Hexagon/HexagonInstrInfo.cpp4
-rw-r--r--lib/Target/Hexagon/HexagonPseudo.td39
-rw-r--r--lib/Target/Hexagon/HexagonRegisterInfo.cpp5
-rw-r--r--lib/Target/Hexagon/HexagonRegisterInfo.h1
-rw-r--r--lib/Target/Hexagon/HexagonVLIWPacketizer.cpp4
-rw-r--r--lib/Target/LLVMBuild.txt1
-rw-r--r--lib/Target/MSP430/MSP430.td14
-rw-r--r--lib/Target/MSP430/MSP430ISelDAGToDAG.cpp4
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp27
-rw-r--r--lib/Target/MSP430/MSP430InstrInfo.td5
-rw-r--r--lib/Target/MSP430/MSP430RegisterInfo.cpp2
-rw-r--r--lib/Target/MSP430/MSP430Subtarget.cpp27
-rw-r--r--lib/Target/MSP430/MSP430Subtarget.h11
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp34
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp7
-rw-r--r--lib/Target/Mips/MipsSubtarget.h7
-rw-r--r--lib/Target/Nios2/CMakeLists.txt18
-rw-r--r--lib/Target/Nios2/LLVMBuild.txt61
-rw-r--r--lib/Target/Nios2/MCTargetDesc/CMakeLists.txt2
-rw-r--r--lib/Target/Nios2/MCTargetDesc/LLVMBuild.txt25
-rw-r--r--lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.cpp25
-rw-r--r--lib/Target/Nios2/MCTargetDesc/Nios2MCTargetDesc.h34
-rw-r--r--lib/Target/Nios2/Nios2.h25
-rw-r--r--lib/Target/Nios2/Nios2.td29
-rw-r--r--lib/Target/Nios2/Nios2InstrFormats.td117
-rw-r--r--lib/Target/Nios2/Nios2InstrInfo.td50
-rw-r--r--lib/Target/Nios2/Nios2RegisterInfo.td60
-rw-r--r--lib/Target/Nios2/Nios2TargetMachine.cpp46
-rw-r--r--lib/Target/Nios2/Nios2TargetMachine.h30
-rw-r--r--lib/Target/Nios2/TargetInfo/CMakeLists.txt1
-rw-r--r--lib/Target/Nios2/TargetInfo/LLVMBuild.txt23
-rw-r--r--lib/Target/Nios2/TargetInfo/Nios2TargetInfo.cpp24
-rw-r--r--lib/Target/PowerPC/PPCExpandISEL.cpp2
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp92
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.h6
-rw-r--r--lib/Target/PowerPC/PPCInstr64Bit.td4
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp2
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.td2
-rw-r--r--lib/Target/PowerPC/PPCInstrVSX.td76
-rw-r--r--lib/Target/SystemZ/SystemZExpandPseudo.cpp2
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.cpp30
-rw-r--r--lib/Target/SystemZ/SystemZTargetTransformInfo.h1
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp5
-rw-r--r--lib/Target/X86/CMakeLists.txt1
-rw-r--r--lib/Target/X86/X86.td3
-rw-r--r--lib/Target/X86/X86FloatingPoint.cpp4
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp8
-rw-r--r--lib/Target/X86/X86InstrAVX512.td152
-rw-r--r--lib/Target/X86/X86InstrArithmetic.td24
-rw-r--r--lib/Target/X86/X86InstrFMA.td13
-rw-r--r--lib/Target/X86/X86InstrFormats.td10
-rw-r--r--lib/Target/X86/X86InstrInfo.cpp3406
-rw-r--r--lib/Target/X86/X86InstrInfo.td23
-rw-r--r--lib/Target/X86/X86InstrMMX.td5
-rw-r--r--lib/Target/X86/X86InstrSSE.td66
-rw-r--r--lib/Target/X86/X86InstrXOP.td8
-rw-r--r--lib/Target/X86/X86InstructionSelector.cpp20
-rw-r--r--lib/Target/X86/X86LegalizerInfo.cpp17
-rw-r--r--lib/Target/X86/X86LegalizerInfo.h1
-rw-r--r--lib/Target/X86/X86Subtarget.cpp1
-rw-r--r--lib/Target/X86/X86Subtarget.h4
-rw-r--r--lib/Transforms/Coroutines/CoroCleanup.cpp1
-rw-r--r--lib/Transforms/Coroutines/CoroEarly.cpp3
-rw-r--r--lib/Transforms/Coroutines/CoroElide.cpp1
-rw-r--r--lib/Transforms/Coroutines/CoroFrame.cpp33
-rw-r--r--lib/Transforms/Coroutines/CoroSplit.cpp86
-rw-r--r--lib/Transforms/IPO/PartialInlining.cpp10
-rw-r--r--lib/Transforms/IPO/PassManagerBuilder.cpp15
-rw-r--r--lib/Transforms/InstCombine/InstCombineAddSub.cpp14
-rw-r--r--lib/Transforms/InstCombine/InstCombineAndOrXor.cpp12
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp8
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp16
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp48
-rw-r--r--lib/Transforms/InstCombine/InstCombineInternal.h6
-rw-r--r--lib/Transforms/InstCombine/InstCombineMulDivRem.cpp8
-rw-r--r--lib/Transforms/InstCombine/InstCombineShifts.cpp3
-rw-r--r--lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp92
-rw-r--r--lib/Transforms/InstCombine/InstructionCombining.cpp19
-rw-r--r--lib/Transforms/Instrumentation/PGOInstrumentation.cpp2
-rw-r--r--lib/Transforms/Instrumentation/SanitizerCoverage.cpp5
-rw-r--r--lib/Transforms/Scalar/CMakeLists.txt1
-rw-r--r--lib/Transforms/Scalar/ConstantHoisting.cpp6
-rw-r--r--lib/Transforms/Scalar/GVN.cpp164
-rw-r--r--lib/Transforms/Scalar/GVNSink.cpp872
-rw-r--r--lib/Transforms/Scalar/GuardWidening.cpp4
-rw-r--r--lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp7
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp42
-rw-r--r--lib/Transforms/Scalar/LoopIdiomRecognize.cpp33
-rw-r--r--lib/Transforms/Scalar/LoopUnswitch.cpp7
-rw-r--r--lib/Transforms/Scalar/NewGVN.cpp70
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp3
-rw-r--r--lib/Transforms/Scalar/SROA.cpp2
-rw-r--r--lib/Transforms/Scalar/Scalar.cpp1
-rw-r--r--lib/Transforms/Scalar/SimpleLoopUnswitch.cpp76
-rw-r--r--lib/Transforms/Utils/CloneFunction.cpp2
-rw-r--r--lib/Transforms/Utils/FunctionComparator.cpp10
-rw-r--r--lib/Transforms/Utils/InlineFunction.cpp7
-rw-r--r--lib/Transforms/Utils/Local.cpp68
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp50
-rw-r--r--lib/Transforms/Utils/SimplifyLibCalls.cpp4
-rw-r--r--lib/Transforms/Vectorize/LoopVectorize.cpp157
-rw-r--r--test/Analysis/CostModel/AArch64/falkor.ll26
-rw-r--r--test/Analysis/Delinearization/constant_functions_multi_dim.ll80
-rw-r--r--test/Analysis/IVUsers/quadradic-exit-value.ll36
-rw-r--r--test/Analysis/ScalarEvolution/different-loops-recs.ll64
-rw-r--r--test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll2
-rw-r--r--test/CodeGen/AArch64/GlobalISel/gisel-commandline-option.ll5
-rw-r--r--test/CodeGen/AArch64/GlobalISel/localizer-in-O0-pipeline.mir96
-rw-r--r--test/CodeGen/AArch64/GlobalISel/localizer.mir312
-rw-r--r--test/CodeGen/AArch64/aarch64-stp-cluster.ll2
-rw-r--r--test/CodeGen/AArch64/arm64-csldst-mmo.ll2
-rw-r--r--test/CodeGen/AArch64/arm64-inline-asm.ll7
-rw-r--r--test/CodeGen/AArch64/arm64-ldp-cluster.ll4
-rw-r--r--test/CodeGen/AArch64/arm64-misched-basic-A53.ll4
-rw-r--r--test/CodeGen/AArch64/arm64-misched-basic-A57.ll2
-rw-r--r--test/CodeGen/AArch64/arm64-misched-forwarding-A53.ll2
-rw-r--r--test/CodeGen/AArch64/arm64-misched-memdep-bug.ll2
-rw-r--r--test/CodeGen/AArch64/arm64-misched-multimmo.ll2
-rw-r--r--test/CodeGen/AArch64/arm64-vabs.ll24
-rw-r--r--test/CodeGen/AArch64/arm64-vadd.ll12
-rw-r--r--test/CodeGen/AArch64/arm64-vmul.ll24
-rw-r--r--test/CodeGen/AArch64/arm64-vshift.ll12
-rw-r--r--test/CodeGen/AArch64/arm64-vsub.ll24
-rw-r--r--test/CodeGen/AArch64/asm-print-comments.ll17
-rw-r--r--test/CodeGen/AArch64/cmpxchg-O0.ll10
-rw-r--r--test/CodeGen/AArch64/fast-isel-cmpxchg.ll9
-rw-r--r--test/CodeGen/AArch64/live-interval-analysis.mir4
-rw-r--r--test/CodeGen/AArch64/misched-fusion-aes.ll145
-rw-r--r--test/CodeGen/AArch64/optimize-imm.ll19
-rw-r--r--test/CodeGen/AArch64/scheduledag-constreg.mir2
-rw-r--r--test/CodeGen/AArch64/tailcall_misched_graph.ll2
-rw-r--r--test/CodeGen/AMDGPU/GlobalISel/legalize-constant.mir20
-rw-r--r--test/CodeGen/AMDGPU/bfe-combine.ll41
-rw-r--r--test/CodeGen/AMDGPU/extload-align.ll4
-rw-r--r--test/CodeGen/AMDGPU/kernel-args.ll4
-rw-r--r--test/CodeGen/AMDGPU/llvm.amdgcn.s.getpc.ll15
-rw-r--r--test/CodeGen/AMDGPU/load-constant-i16.ll2
-rw-r--r--test/CodeGen/AMDGPU/load-constant-i8.ll2
-rw-r--r--test/CodeGen/AMDGPU/load-global-i16.ll4
-rw-r--r--test/CodeGen/AMDGPU/load-global-i8.ll4
-rw-r--r--test/CodeGen/AMDGPU/load-local-i16.ll2
-rw-r--r--test/CodeGen/AMDGPU/load-local-i8.ll2
-rw-r--r--test/CodeGen/AMDGPU/min.ll2
-rw-r--r--test/CodeGen/AMDGPU/parallelandifcollapse.ll2
-rw-r--r--test/CodeGen/AMDGPU/r600.bitcast.ll2
-rw-r--r--test/CodeGen/AMDGPU/schedule-regpressure.mir2
-rw-r--r--test/CodeGen/AMDGPU/setcc.ll2
-rw-r--r--test/CodeGen/AMDGPU/shl-add-to-add-shl.ll40
-rw-r--r--test/CodeGen/AMDGPU/shl.ll2
-rw-r--r--test/CodeGen/AMDGPU/sra.ll2
-rw-r--r--test/CodeGen/AMDGPU/store-global.ll4
-rw-r--r--test/CodeGen/AMDGPU/store-private.ll4
-rw-r--r--test/CodeGen/AMDGPU/sub.ll2
-rw-r--r--test/CodeGen/AMDGPU/unknown-processor.ll4
-rw-r--r--test/CodeGen/AMDGPU/vector-alloca.ll22
-rw-r--r--test/CodeGen/ARM/GlobalISel/arm-irtranslator.ll354
-rw-r--r--test/CodeGen/ARM/GlobalISel/arm-unsupported.ll12
-rw-r--r--test/CodeGen/ARM/arm-shrink-wrapping.ll7
-rw-r--r--test/CodeGen/ARM/constantpool-promote-dbg.ll2
-rw-r--r--test/CodeGen/ARM/constantpool-promote-ldrh.ll4
-rw-r--r--test/CodeGen/ARM/constantpool-promote.ll24
-rw-r--r--test/CodeGen/ARM/cortexr52-misched-basic.ll4
-rw-r--r--test/CodeGen/ARM/fastisel-thumb-litpool.ll1
-rw-r--r--test/CodeGen/ARM/memcpy-inline.ll13
-rw-r--r--test/CodeGen/ARM/memset-inline.ll84
-rw-r--r--test/CodeGen/ARM/misched-copy-arm.ll2
-rw-r--r--test/CodeGen/ARM/misched-fp-basic.ll6
-rw-r--r--test/CodeGen/ARM/misched-int-basic-thumb2.mir6
-rw-r--r--test/CodeGen/ARM/misched-int-basic.mir6
-rw-r--r--test/CodeGen/ARM/single-issue-r52.mir4
-rw-r--r--test/CodeGen/ARM/vcombine.ll4
-rw-r--r--test/CodeGen/ARM/vext.ll8
-rw-r--r--test/CodeGen/Hexagon/post-ra-kill-update.mir2
-rw-r--r--test/CodeGen/Lanai/lanai-misched-trivial-disjoint.ll2
-rw-r--r--test/CodeGen/MIR/ARM/PR32721_ifcvt_triangle_unanalyzable.mir24
-rw-r--r--test/CodeGen/MSP430/hwmult16.ll1
-rw-r--r--test/CodeGen/MSP430/hwmult32.ll1
-rw-r--r--test/CodeGen/MSP430/hwmultf5.ll1
-rw-r--r--test/CodeGen/MSP430/vararg.ll2
-rw-r--r--test/CodeGen/Nios2/lit.local.cfg3
-rw-r--r--test/CodeGen/Nios2/target_support.ll11
-rw-r--r--test/CodeGen/PowerPC/atomics-constant.ll23
-rw-r--r--test/CodeGen/PowerPC/build-vector-tests.ll216
-rw-r--r--test/CodeGen/PowerPC/livephysregs.mir52
-rw-r--r--test/CodeGen/PowerPC/p8altivec-shuffles-pred.ll2
-rw-r--r--test/CodeGen/PowerPC/p9-xxinsertw-xxextractuw.ll72
-rw-r--r--test/CodeGen/PowerPC/ppc64-i128-abi.ll8
-rw-r--r--test/CodeGen/PowerPC/pr25157-peephole.ll2
-rw-r--r--test/CodeGen/PowerPC/pr27078.ll8
-rw-r--r--test/CodeGen/PowerPC/swaps-le-6.ll8
-rw-r--r--test/CodeGen/PowerPC/vec_sldwi.ll307
-rw-r--r--test/CodeGen/PowerPC/vsx-ldst-builtin-le.ll48
-rw-r--r--test/CodeGen/PowerPC/vsx-ldst.ll4
-rw-r--r--test/CodeGen/PowerPC/vsx-p9.ll72
-rw-r--r--test/CodeGen/PowerPC/vsx_insert_extract_le.ll4
-rw-r--r--test/CodeGen/PowerPC/vsx_shuffle_le.ll48
-rw-r--r--test/CodeGen/Thumb/machine-cse-physreg.mir35
-rw-r--r--test/CodeGen/X86/2009-02-26-MachineLICMBug.ll2
-rw-r--r--test/CodeGen/X86/GlobalISel/memop-vec.ll113
-rw-r--r--test/CodeGen/X86/GlobalISel/regbankselect-AVX2.mir55
-rw-r--r--test/CodeGen/X86/GlobalISel/regbankselect-AVX512.mir87
-rw-r--r--test/CodeGen/X86/GlobalISel/select-leaf-constant.mir96
-rw-r--r--test/CodeGen/X86/GlobalISel/select-memop-v256.mir188
-rw-r--r--test/CodeGen/X86/GlobalISel/select-memop-v512.mir127
-rw-r--r--test/CodeGen/X86/avx-vzeroupper.ll221
-rw-r--r--test/CodeGen/X86/avx512bw-intrinsics.ll6
-rw-r--r--test/CodeGen/X86/avx512vpopcntdq-intrinsics.ll88
-rw-r--r--test/CodeGen/X86/fast-isel-select-cmp.ll10
-rw-r--r--test/CodeGen/X86/fp-intrinsics.ll147
-rw-r--r--test/CodeGen/X86/hoist-invariant-load.ll2
-rw-r--r--test/CodeGen/X86/misched-copy.ll2
-rw-r--r--test/CodeGen/X86/or-branch.ll66
-rw-r--r--test/CodeGen/X86/pr27681.mir2
-rw-r--r--test/CodeGen/X86/sandybridge-loads.ll42
-rw-r--r--test/CodeGen/X86/sse42-intrinsics-fast-isel.ll6
-rw-r--r--test/CodeGen/X86/stack-folding-fp-avx1.ll21
-rw-r--r--test/CodeGen/X86/twoaddr-coalesce-2.ll2
-rw-r--r--test/CodeGen/X86/vector-narrow-binop.ll63
-rw-r--r--test/CodeGen/X86/vector-popcnt-128.ll109
-rw-r--r--test/CodeGen/X86/vector-popcnt-256.ll42
-rw-r--r--test/CodeGen/X86/vector-popcnt-512.ll53
-rw-r--r--test/CodeGen/X86/vector-shuffle-512-v16.ll3
-rw-r--r--test/CodeGen/X86/vector-shuffle-avx512.ll34
-rw-r--r--test/CodeGen/X86/vector-sqrt.ll18
-rw-r--r--test/CodeGen/X86/vector-trunc-math.ll6
-rw-r--r--test/CodeGen/X86/vector-tzcnt-128.ll159
-rw-r--r--test/CodeGen/X86/vector-tzcnt-256.ll379
-rw-r--r--test/CodeGen/X86/vector-tzcnt-512.ll153
-rw-r--r--test/CodeGen/X86/wide-integer-cmp.ll1
-rw-r--r--test/CodeGen/X86/widened-broadcast.ll73
-rw-r--r--test/CodeGen/X86/x86-interleaved-access.ll12
-rw-r--r--test/CodeGen/X86/x87.ll11
-rw-r--r--test/CodeGen/XCore/epilogue_prologue.ll24
-rw-r--r--test/DebugInfo/Generic/empty.ll9
-rw-r--r--test/DebugInfo/Generic/nodebug.ll13
-rw-r--r--test/DebugInfo/Generic/skeletoncu.ll4
-rw-r--r--test/DebugInfo/Inputs/split-dwarf-dwp.cpp12
-rw-r--r--test/DebugInfo/Inputs/split-dwarf-dwp.obin0 -> 2744 bytes
-rw-r--r--test/DebugInfo/Inputs/split-dwarf-dwp.o.dwpbin0 -> 1256 bytes
-rw-r--r--test/DebugInfo/MIR/X86/empty-inline.mir122
-rw-r--r--test/DebugInfo/PDB/Inputs/merge-ids-1.yaml36
-rw-r--r--test/DebugInfo/PDB/Inputs/merge-ids-2.yaml31
-rw-r--r--test/DebugInfo/PDB/Inputs/merge-ids-and-types-1.yaml113
-rw-r--r--test/DebugInfo/PDB/Inputs/merge-ids-and-types-2.yaml143
-rw-r--r--test/DebugInfo/PDB/Inputs/merge-types-1.yaml (renamed from test/DebugInfo/PDB/Inputs/merge1.yaml)0
-rw-r--r--test/DebugInfo/PDB/Inputs/merge-types-2.yaml (renamed from test/DebugInfo/PDB/Inputs/merge2.yaml)0
-rw-r--r--test/DebugInfo/PDB/Inputs/source-names-1.yaml8
-rw-r--r--test/DebugInfo/PDB/Inputs/source-names-2.yaml8
-rw-r--r--test/DebugInfo/PDB/pdbdump-merge-ids-and-types.test65
-rw-r--r--test/DebugInfo/PDB/pdbdump-mergeids.test31
-rw-r--r--test/DebugInfo/PDB/pdbdump-mergetypes.test4
-rw-r--r--test/DebugInfo/PDB/pdbdump-objfilename.yaml14
-rw-r--r--test/DebugInfo/PDB/pdbdump-source-names.test20
-rw-r--r--test/DebugInfo/X86/array.ll150
-rw-r--r--test/DebugInfo/X86/dbg-value-frame-index.ll2
-rw-r--r--test/DebugInfo/X86/debug-loc-offset.ll8
-rw-r--r--test/DebugInfo/X86/debug-macro.ll72
-rw-r--r--test/DebugInfo/X86/empty.ll11
-rw-r--r--test/DebugInfo/X86/fission-hash.ll10
-rw-r--r--test/DebugInfo/X86/gnu-public-names-empty.ll9
-rw-r--r--test/DebugInfo/X86/gnu-public-names-gmlt.ll68
-rw-r--r--test/DebugInfo/X86/split-dwarf-multiple-cu-hash.ll42
-rw-r--r--test/DebugInfo/X86/split-dwarf-omit-empty.ll54
-rw-r--r--test/DebugInfo/dwo.ll4
-rw-r--r--test/DebugInfo/llvm-symbolizer.test8
-rw-r--r--test/DebugInfo/omit-empty.ll12
-rw-r--r--test/DebugInfo/skeletoncu.ll4
-rw-r--r--test/ExecutionEngine/MCJIT/lit.local.cfg3
-rw-r--r--test/ExecutionEngine/OrcMCJIT/lit.local.cfg3
-rw-r--r--test/ExecutionEngine/OrcMCJIT/pr32650.ll28
-rw-r--r--test/Feature/fp-intrinsics.ll148
-rw-r--r--test/Instrumentation/SanitizerCoverage/chains.ll33
-rw-r--r--test/Instrumentation/SanitizerCoverage/postdominator_check.ll85
-rw-r--r--test/LTO/Resolution/X86/linkonce.ll11
-rw-r--r--test/LTO/Resolution/X86/type-checked-load.ll16
-rw-r--r--test/Linker/Inputs/module-flags-pic-2-b.ll5
-rw-r--r--test/Linker/module-flags-pic-2-a.ll13
-rw-r--r--test/MC/AMDGPU/vop_sdwa.s441
-rw-r--r--test/MC/Disassembler/AMDGPU/sdwa_gfx9.txt477
-rw-r--r--test/MC/Disassembler/X86/avx-512.txt23
-rw-r--r--test/MC/WebAssembly/unnamed-data.ll53
-rw-r--r--test/MC/X86/pr22004.s3
-rw-r--r--test/MC/X86/x86-64-avx512vpopcntdq.s225
-rw-r--r--test/Other/new-pm-defaults.ll1
-rw-r--r--test/TableGen/GlobalISelEmitter.td26
-rw-r--r--test/Transforms/Coroutines/coro-debug.ll142
-rw-r--r--test/Transforms/Coroutines/coro-frame.ll11
-rw-r--r--test/Transforms/Coroutines/coro-materialize.ll52
-rw-r--r--test/Transforms/EarlyCSE/const-speculation.ll39
-rw-r--r--test/Transforms/GVN/PRE/phi-translate-2.ll105
-rw-r--r--test/Transforms/GVN/PRE/pre-gep-load.ll2
-rw-r--r--test/Transforms/GVN/PRE/pre-load.ll6
-rw-r--r--test/Transforms/GVNSink/dither.ll42
-rw-r--r--test/Transforms/GVNSink/indirect-call.ll70
-rw-r--r--test/Transforms/GVNSink/sink-common-code.ll694
-rw-r--r--test/Transforms/GVNSink/struct.ll71
-rw-r--r--test/Transforms/GlobalDCE/externally_available.ll19
-rw-r--r--test/Transforms/Inline/prof-update-instr.ll57
-rw-r--r--test/Transforms/Inline/prof-update-sample.ll (renamed from test/Transforms/Inline/prof-update.ll)0
-rw-r--r--test/Transforms/InstCombine/2008-07-10-ICmpBinOp.ll19
-rw-r--r--test/Transforms/InstCombine/2008-08-17-ICmpXorSignbit.ll87
-rw-r--r--test/Transforms/InstCombine/alloca.ll7
-rw-r--r--test/Transforms/InstCombine/bitcast-vec-canon.ll37
-rw-r--r--test/Transforms/InstCombine/bitcast.ll45
-rw-r--r--test/Transforms/InstCombine/ctpop.ll27
-rw-r--r--test/Transforms/InstCombine/icmp-xor-signbit.ll228
-rw-r--r--test/Transforms/InstCombine/icmp.ll64
-rw-r--r--test/Transforms/InstSimplify/call.ll253
-rw-r--r--test/Transforms/InstSimplify/or.ll41
-rw-r--r--test/Transforms/JumpThreading/assume.ll145
-rw-r--r--test/Transforms/JumpThreading/fold-not-thread.ll4
-rw-r--r--test/Transforms/JumpThreading/guards.ll87
-rw-r--r--test/Transforms/LoopIdiom/pr33114.ll35
-rw-r--r--test/Transforms/LoopStrengthReduce/X86/incorrect-offset-scaling.ll12
-rw-r--r--test/Transforms/LoopStrengthReduce/X86/lsr-expand-quadratic.ll (renamed from test/Transforms/LoopStrengthReduce/lsr-expand-quadratic.ll)26
-rw-r--r--test/Transforms/LoopStrengthReduce/nonintegral.ll45
-rw-r--r--test/Transforms/LoopStrengthReduce/post-inc-icmpzero.ll4
-rw-r--r--test/Transforms/LoopVectorize/AArch64/no_vector_instructions.ll26
-rw-r--r--test/Transforms/LoopVectorize/SystemZ/addressing.ll72
-rw-r--r--test/Transforms/LoopVectorize/X86/vectorization-remarks-missed.ll124
-rw-r--r--test/Transforms/NewGVN/pr32403.ll3
-rw-r--r--test/Transforms/NewGVN/pr32836.ll45
-rw-r--r--test/Transforms/SimpleLoopUnswitch/trivial-unswitch.ll61
-rw-r--r--test/Verifier/fp-intrinsics.ll39
-rw-r--r--test/Verifier/module-flags-1.ll6
-rw-r--r--test/tools/gold/X86/relocation-model-pic.ll63
-rw-r--r--test/tools/llvm-nm/X86/Inputs/example.libbin0 -> 2000 bytes
-rw-r--r--test/tools/llvm-nm/X86/importlibrary.test7
-rw-r--r--test/tools/llvm-profdata/memop-size-prof.proftext2
-rw-r--r--tools/gold/gold-plugin.cpp6
-rw-r--r--tools/llvm-nm/llvm-nm.cpp17
-rw-r--r--tools/llvm-pdbdump/PrettyClassLayoutGraphicalDumper.cpp3
-rw-r--r--tools/llvm-pdbdump/YAMLOutputStyle.cpp14
-rw-r--r--tools/llvm-pdbdump/llvm-pdbdump.cpp37
-rw-r--r--tools/llvm-pdbdump/llvm-pdbdump.h1
-rw-r--r--tools/llvm-profdata/llvm-profdata.cpp2
-rw-r--r--tools/llvm-readobj/COFFDumper.cpp4
-rw-r--r--unittests/Analysis/ScalarEvolutionTest.cpp88
-rw-r--r--unittests/DebugInfo/CodeView/CMakeLists.txt1
-rw-r--r--unittests/DebugInfo/CodeView/ErrorChecking.h9
-rw-r--r--unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp496
-rw-r--r--unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp24
-rw-r--r--unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp51
-rw-r--r--unittests/IR/BasicBlockTest.cpp75
-rw-r--r--unittests/IR/CMakeLists.txt1
-rw-r--r--unittests/IR/DominatorTreeTest.cpp129
-rw-r--r--unittests/Support/CrashRecoveryTest.cpp4
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp92
-rw-r--r--utils/TableGen/TableGen.cpp6
-rw-r--r--utils/TableGen/TableGenBackends.h1
-rw-r--r--utils/TableGen/X86FoldTablesEmitter.cpp720
-rwxr-xr-xutils/abtest.py (renamed from utils/abtest/abtest.py)58
-rwxr-xr-xutils/abtest/mark_aarch64fns.py65
-rwxr-xr-xutils/abtest/mark_armfns.py54
-rwxr-xr-xutils/git-svn/git-llvm10
-rw-r--r--utils/lit/lit/TestRunner.py2
-rwxr-xr-xutils/release/merge-request.sh2
641 files changed, 20470 insertions, 10062 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 78e2e0166257..a5b96569f9c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,13 @@ if (NOT PACKAGE_VERSION)
"${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}${LLVM_VERSION_SUFFIX}")
endif()
+if ((CMAKE_GENERATOR MATCHES "Visual Studio") AND (CMAKE_GENERATOR_TOOLSET STREQUAL ""))
+ message(WARNING "Visual Studio generators use the x86 host compiler by "
+ "default, even for 64-bit targets. This can result in linker "
+ "instability and out of memory errors. To use the 64-bit "
+ "host compiler, pass -Thost=x64 on the CMake command line.")
+endif()
+
project(LLVM
${cmake_3_0_PROJ_VERSION}
${cmake_3_0_LANGUAGES}
diff --git a/docs/Benchmarking.rst b/docs/Benchmarking.rst
new file mode 100644
index 000000000000..0f88db745a68
--- /dev/null
+++ b/docs/Benchmarking.rst
@@ -0,0 +1,87 @@
+==================================
+Benchmarking tips
+==================================
+
+
+Introduction
+============
+
+For benchmarking a patch we want to reduce all possible sources of
+noise as much as possible. How to do that is very OS dependent.
+
+Note that low noise is required, but not sufficient. It does not
+exclude measurement bias. See
+https://www.cis.upenn.edu/~cis501/papers/producing-wrong-data.pdf for
+example.
+
+General
+================================
+
+* Use a high resolution timer, e.g. perf under linux.
+
+* Run the benchmark multiple times to be able to recognize noise.
+
+* Disable as many processes or services as possible on the target system.
+
+* Disable frequency scaling, turbo boost and address space
+ randomization (see OS specific section).
+
+* Static link if the OS supports it. That avoids any variation that
+ might be introduced by loading dynamic libraries. This can be done
+ by passing ``-DLLVM_BUILD_STATIC=ON`` to cmake.
+
+* Try to avoid storage. On some systems you can use tmpfs. Putting the
+ program, inputs and outputs on tmpfs avoids touching a real storage
+ system, which can have a pretty big variability.
+
+ To mount it (on linux and freebsd at least)::
+
+ mount -t tmpfs -o size=<XX>g none dir_to_mount
+
+Linux
+=====
+
+* Disable address space randomization::
+
+ echo 0 > /proc/sys/kernel/randomize_va_space
+
+* Set scaling_governor to performance::
+
+ for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
+ do
+ echo performance > /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
+ done
+
+* Use https://github.com/lpechacek/cpuset to reserve cpus for just the
+ program you are benchmarking. If using perf, leave at least 2 cores
+ so that perf runs in one and your program in another::
+
+ cset shield -c N1,N2 -k on
+
+ This will move all threads out of N1 and N2. The ``-k on`` means
+ that even kernel threads are moved out.
+
+* Disable the SMT pair of the cpus you will use for the benchmark. The
+ pair of cpu N can be found in
+ ``/sys/devices/system/cpu/cpuN/topology/thread_siblings_list`` and
+ disabled with::
+
+ echo 0 > /sys/devices/system/cpu/cpuX/online
+
+
+* Run the program with::
+
+ cset shield --exec -- perf stat -r 10 <cmd>
+
+ This will run the command after ``--`` in the isolated cpus. The
+ particular perf command runs the ``<cmd>`` 10 times and reports
+ statistics.
+
+With these in place you can expect perf variations of less than 0.1%.
+
+Linux Intel
+-----------
+
+* Disable turbo mode::
+
+ echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo
diff --git a/docs/GettingStartedVS.rst b/docs/GettingStartedVS.rst
index 1e4676767939..50f7aa123c55 100644
--- a/docs/GettingStartedVS.rst
+++ b/docs/GettingStartedVS.rst
@@ -100,6 +100,10 @@ Here's the short story for getting up and running quickly with LLVM:
* CMake generates project files for all build types. To select a specific
build type, use the Configuration manager from the VS IDE or the
``/property:Configuration`` command line option when using MSBuild.
+ * By default, the Visual Studio project files generated by CMake use the
+ 32-bit toolset. If you are developing on a 64-bit version of Windows and
+ want to use the 64-bit toolset, pass the ``-Thost=x64`` flag when
+ generating the Visual Studio solution. This requires CMake 3.8.0 or later.
6. Start Visual Studio
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index b205cae9b118..2e339183ef11 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -4415,12 +4415,6 @@ The current supported vocabulary is limited:
address space identifier.
- ``DW_OP_stack_value`` marks a constant value.
-DIExpression nodes that contain a ``DW_OP_stack_value`` operator are standalone
-location descriptions that describe constant values. This form is used to
-describe global constants that have been optimized away. All other expressions
-are modifiers to another location: A debug intrinsic ties a location and a
-DIExpression together.
-
DWARF specifies three kinds of simple location descriptions: Register, memory,
and implicit location descriptions. Register and memory location descriptions
describe the *location* of a source variable (in the sense that a debugger might
@@ -12722,7 +12716,7 @@ Syntax:
declare <type>
@llvm.experimental.constrained.fadd(<type> <op1>, <type> <op2>,
metadata <rounding mode>,
- metadata <exception behavior>)
+ metadata <exception behavior>)
Overview:
"""""""""
@@ -12759,7 +12753,7 @@ Syntax:
declare <type>
@llvm.experimental.constrained.fsub(<type> <op1>, <type> <op2>,
metadata <rounding mode>,
- metadata <exception behavior>)
+ metadata <exception behavior>)
Overview:
"""""""""
@@ -12796,7 +12790,7 @@ Syntax:
declare <type>
@llvm.experimental.constrained.fmul(<type> <op1>, <type> <op2>,
metadata <rounding mode>,
- metadata <exception behavior>)
+ metadata <exception behavior>)
Overview:
"""""""""
@@ -12833,7 +12827,7 @@ Syntax:
declare <type>
@llvm.experimental.constrained.fdiv(<type> <op1>, <type> <op2>,
metadata <rounding mode>,
- metadata <exception behavior>)
+ metadata <exception behavior>)
Overview:
"""""""""
@@ -12870,7 +12864,7 @@ Syntax:
declare <type>
@llvm.experimental.constrained.frem(<type> <op1>, <type> <op2>,
metadata <rounding mode>,
- metadata <exception behavior>)
+ metadata <exception behavior>)
Overview:
"""""""""
@@ -12899,6 +12893,461 @@ value operands and has the same type as the operands. The remainder has the
same sign as the dividend.
+Constrained libm-equivalent Intrinsics
+--------------------------------------
+
+In addition to the basic floating point operations for which constrained
+intrinsics are described above, there are constrained versions of various
+operations which provide equivalent behavior to a corresponding libm function.
+These intrinsics allow the precise behavior of these operations with respect to
+rounding mode and exception behavior to be controlled.
+
+As with the basic constrained floating point intrinsics, the rounding mode
+and exception behavior arguments only control the behavior of the optimizer.
+They do not change the runtime floating point environment.
+
+
+'``llvm.experimental.constrained.sqrt``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.sqrt(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.sqrt``' intrinsic returns the square root
+of the specified value, returning the same value as the libm '``sqrt``'
+functions would, but without setting ``errno``.
+
+Arguments:
+""""""""""
+
+The first argument and the return type are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the nonnegative square root of the specified value.
+If the value is less than negative zero, a floating point exception occurs
+and the the return value is architecture specific.
+
+
+'``llvm.experimental.constrained.pow``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.pow(<type> <op1>, <type> <op2>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.pow``' intrinsic returns the first operand
+raised to the (positive or negative) power specified by the second operand.
+
+Arguments:
+""""""""""
+
+The first two arguments and the return value are floating point numbers of the
+same type. The second argument specifies the power to which the first argument
+should be raised.
+
+The third and fourth arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the first value raised to the second power,
+returning the same values as the libm ``pow`` functions would, and
+handles error conditions in the same way.
+
+
+'``llvm.experimental.constrained.powi``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.powi(<type> <op1>, i32 <op2>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.powi``' intrinsic returns the first operand
+raised to the (positive or negative) power specified by the second operand. The
+order of evaluation of multiplications is not defined. When a vector of floating
+point type is used, the second argument remains a scalar integer value.
+
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type. The second argument is a 32-bit signed integer specifying the power to
+which the first argument should be raised.
+
+The third and fourth arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the first value raised to the second power with an
+unspecified sequence of rounding operations.
+
+
+'``llvm.experimental.constrained.sin``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.sin(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.sin``' intrinsic returns the sine of the
+first operand.
+
+Arguments:
+""""""""""
+
+The first argument and the return type are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the sine of the specified operand, returning the
+same values as the libm ``sin`` functions would, and handles error
+conditions in the same way.
+
+
+'``llvm.experimental.constrained.cos``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.cos(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.cos``' intrinsic returns the cosine of the
+first operand.
+
+Arguments:
+""""""""""
+
+The first argument and the return type are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the cosine of the specified operand, returning the
+same values as the libm ``cos`` functions would, and handles error
+conditions in the same way.
+
+
+'``llvm.experimental.constrained.exp``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.exp(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.exp``' intrinsic computes the base-e
+exponential of the specified value.
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the same values as the libm ``exp`` functions
+would, and handles error conditions in the same way.
+
+
+'``llvm.experimental.constrained.exp2``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.exp2(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.exp2``' intrinsic computes the base-2
+exponential of the specified value.
+
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the same values as the libm ``exp2`` functions
+would, and handles error conditions in the same way.
+
+
+'``llvm.experimental.constrained.log``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.log(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.log``' intrinsic computes the base-e
+logarithm of the specified value.
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+
+Semantics:
+""""""""""
+
+This function returns the same values as the libm ``log`` functions
+would, and handles error conditions in the same way.
+
+
+'``llvm.experimental.constrained.log10``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.log10(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.log10``' intrinsic computes the base-10
+logarithm of the specified value.
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the same values as the libm ``log10`` functions
+would, and handles error conditions in the same way.
+
+
+'``llvm.experimental.constrained.log2``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.log2(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.log2``' intrinsic computes the base-2
+logarithm of the specified value.
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the same values as the libm ``log2`` functions
+would, and handles error conditions in the same way.
+
+
+'``llvm.experimental.constrained.rint``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.rint(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.rint``' intrinsic returns the first
+operand rounded to the nearest integer. It may raise an inexact floating point
+exception if the operand is not an integer.
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the same values as the libm ``rint`` functions
+would, and handles error conditions in the same way. The rounding mode is
+described, not determined, by the rounding mode argument. The actual rounding
+mode is determined by the runtime floating point environment. The rounding
+mode argument is only intended as information to the compiler.
+
+
+'``llvm.experimental.constrained.nearbyint``' Intrinsic
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Syntax:
+"""""""
+
+::
+
+ declare <type>
+ @llvm.experimental.constrained.nearbyint(<type> <op1>,
+ metadata <rounding mode>,
+ metadata <exception behavior>)
+
+Overview:
+"""""""""
+
+The '``llvm.experimental.constrained.nearbyint``' intrinsic returns the first
+operand rounded to the nearest integer. It will not raise an inexact floating
+point exception if the operand is not an integer.
+
+
+Arguments:
+""""""""""
+
+The first argument and the return value are floating point numbers of the same
+type.
+
+The second and third arguments specify the rounding mode and exception
+behavior as described above.
+
+Semantics:
+""""""""""
+
+This function returns the same values as the libm ``nearbyint`` functions
+would, and handles error conditions in the same way. The rounding mode is
+described, not determined, by the rounding mode argument. The actual rounding
+mode is determined by the runtime floating point environment. The rounding
+mode argument is only intended as information to the compiler.
+
+
General Intrinsics
------------------
diff --git a/docs/Vectorizers.rst b/docs/Vectorizers.rst
index 65c19aa2bc0c..a909d458c317 100644
--- a/docs/Vectorizers.rst
+++ b/docs/Vectorizers.rst
@@ -99,7 +99,9 @@ Optimization remarks are enabled using:
indicates if vectorization was specified.
``-Rpass-analysis=loop-vectorize`` identifies the statements that caused
-vectorization to fail.
+vectorization to fail. If in addition ``-fsave-optimization-record`` is
+provided, multiple causes of vectorization failure may be listed (this behavior
+might change in the future).
Consider the following loop:
diff --git a/docs/index.rst b/docs/index.rst
index fe47eb1bcb7f..becbe48e7ec7 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -90,6 +90,7 @@ representation.
CodeOfConduct
CompileCudaWithLLVM
ReportingGuide
+ Benchmarking
:doc:`GettingStarted`
Discusses how to get up and running quickly with the LLVM infrastructure.
diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h
index a14fd1dc20ec..847662cc11be 100644
--- a/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h
+++ b/examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h
@@ -1,4 +1,4 @@
-//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
+//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
@@ -44,7 +44,7 @@ private:
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
public:
- typedef decltype(CompileLayer)::ModuleSetHandleT ModuleHandle;
+ using ModuleHandle = decltype(CompileLayer)::ModuleSetHandleT;
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h
index 2039be4571a5..a5ac2f017b74 100644
--- a/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h
+++ b/examples/Kaleidoscope/BuildingAJIT/Chapter2/KaleidoscopeJIT.h
@@ -1,4 +1,4 @@
-//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
+//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,7 +17,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
@@ -47,13 +47,13 @@ private:
RTDyldObjectLinkingLayer<> ObjectLayer;
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
- typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
- OptimizeFunction;
+ using OptimizeFunction =
+ std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
public:
- typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle;
+ using ModuleHandle = decltype(OptimizeLayer)::ModuleSetHandleT;
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
index d22d41855072..7acb9c748880 100644
--- a/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
+++ b/examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
@@ -1,4 +1,4 @@
-//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
+//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,6 +17,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
@@ -49,8 +50,8 @@ private:
RTDyldObjectLinkingLayer<> ObjectLayer;
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
- typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
- OptimizeFunction;
+ using OptimizeFunction =
+ std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
@@ -58,7 +59,7 @@ private:
CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer;
public:
- typedef decltype(CODLayer)::ModuleSetHandleT ModuleHandle;
+ using ModuleHandle = decltype(CODLayer)::ModuleSetHandleT;
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
index e0a78410f713..03e42230ae71 100644
--- a/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
+++ b/examples/Kaleidoscope/BuildingAJIT/Chapter4/KaleidoscopeJIT.h
@@ -1,4 +1,4 @@
-//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
+//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,10 +17,10 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
@@ -76,8 +76,8 @@ private:
RTDyldObjectLinkingLayer<> ObjectLayer;
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
- typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
- OptimizeFunction;
+ using OptimizeFunction =
+ std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
@@ -85,7 +85,7 @@ private:
std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
public:
- typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle;
+ using ModuleHandle = decltype(OptimizeLayer)::ModuleSetHandleT;
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()),
@@ -106,7 +106,6 @@ public:
TargetMachine &getTargetMachine() { return *TM; }
ModuleHandle addModule(std::unique_ptr<Module> M) {
-
// Build our symbol resolver:
// Lambda 1: Look back into the JIT itself to find symbols that are part of
// the same "logical dylib".
diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h b/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h
index 70a896fe8f00..0ee9d094ab82 100644
--- a/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h
+++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/KaleidoscopeJIT.h
@@ -1,4 +1,4 @@
-//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
+//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,9 +20,8 @@
#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
-#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
@@ -73,7 +72,7 @@ namespace llvm {
namespace orc {
// Typedef the remote-client API.
-typedef remote::OrcRemoteTargetClient<FDRPCChannel> MyRemote;
+using MyRemote = remote::OrcRemoteTargetClient<FDRPCChannel>;
class KaleidoscopeJIT {
private:
@@ -82,8 +81,8 @@ private:
RTDyldObjectLinkingLayer<> ObjectLayer;
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
- typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
- OptimizeFunction;
+ using OptimizeFunction =
+ std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
@@ -92,7 +91,7 @@ private:
MyRemote &Remote;
public:
- typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle;
+ using ModuleHandle = decltype(OptimizeLayer)::ModuleSetHandleT;
KaleidoscopeJIT(MyRemote &Remote)
: TM(EngineBuilder().selectTarget(Triple(Remote.getTargetTriple()), "",
@@ -124,7 +123,6 @@ public:
TargetMachine &getTargetMachine() { return *TM; }
ModuleHandle addModule(std::unique_ptr<Module> M) {
-
// Build our symbol resolver:
// Lambda 1: Look back into the JIT itself to find symbols that are part of
// the same "logical dylib".
diff --git a/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp b/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp
index da6e8ac65234..e50a7ecf96bc 100644
--- a/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp
+++ b/examples/Kaleidoscope/BuildingAJIT/Chapter5/Server/server.cpp
@@ -1,17 +1,19 @@
+#include "../RemoteJITUtils.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h"
+#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetSelect.h"
-#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h"
-#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
-
-#include "../RemoteJITUtils.h"
-
+#include <cstdint>
+#include <cstdio>
#include <cstring>
-#include <unistd.h>
+#include <string>
#include <netinet/in.h>
#include <sys/socket.h>
-
using namespace llvm;
using namespace llvm::orc;
@@ -22,7 +24,7 @@ cl::opt<uint32_t> Port("port",
ExitOnError ExitOnErr;
-typedef int (*MainFun)(int, const char*[]);
+using MainFun = int (*)(int, const char*[]);
template <typename NativePtrT>
NativePtrT MakeNative(uint64_t P) {
@@ -36,7 +38,6 @@ void printExprResult(double Val) {
// --- LAZY COMPILE TEST ---
int main(int argc, char* argv[]) {
-
if (argc == 0)
ExitOnErr.setBanner("jit_server: ");
else
@@ -59,14 +60,14 @@ int main(int argc, char* argv[]) {
int sockfd = socket(PF_INET, SOCK_STREAM, 0);
sockaddr_in servAddr, clientAddr;
socklen_t clientAddrLen = sizeof(clientAddr);
- bzero(&servAddr, sizeof(servAddr));
+ memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = PF_INET;
servAddr.sin_family = INADDR_ANY;
servAddr.sin_port = htons(Port);
{
// avoid "Address already in use" error.
- int yes=1;
+ int yes = 1;
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
errs() << "Error calling setsockopt.\n";
return 1;
@@ -98,7 +99,8 @@ int main(int argc, char* argv[]) {
};
FDRPCChannel TCPChannel(newsockfd, newsockfd);
- typedef remote::OrcRemoteTargetServer<FDRPCChannel, OrcX86_64_SysV> MyServerT;
+
+ using MyServerT = remote::OrcRemoteTargetServer<FDRPCChannel, OrcX86_64_SysV>;
MyServerT Server(TCPChannel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames);
diff --git a/examples/Kaleidoscope/include/KaleidoscopeJIT.h b/examples/Kaleidoscope/include/KaleidoscopeJIT.h
index 1dca39deba3c..9a682f7ab744 100644
--- a/examples/Kaleidoscope/include/KaleidoscopeJIT.h
+++ b/examples/Kaleidoscope/include/KaleidoscopeJIT.h
@@ -1,4 +1,4 @@
-//===----- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope ----*- C++ -*-===//
+//===- KaleidoscopeJIT.h - A simple JIT for Kaleidoscope --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,7 +19,6 @@
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
@@ -40,9 +39,9 @@ namespace orc {
class KaleidoscopeJIT {
public:
- typedef RTDyldObjectLinkingLayer<> ObjLayerT;
- typedef IRCompileLayer<ObjLayerT> CompileLayerT;
- typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;
+ using ObjLayerT = RTDyldObjectLinkingLayer<>;
+ using CompileLayerT = IRCompileLayer<ObjLayerT>;
+ using ModuleHandleT = CompileLayerT::ModuleSetHandleT;
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index 3a4a37017d61..07626982d289 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -59,6 +59,7 @@ public:
mips64, // MIPS64: mips64
mips64el, // MIPS64EL: mips64el
msp430, // MSP430: msp430
+ nios2, // NIOSII: nios2
ppc, // PPC: powerpc
ppc64, // PPC64: powerpc64, ppu
ppc64le, // PPC64LE: powerpc64le
diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h
index bf73e099a2bf..ca48b5483512 100644
--- a/include/llvm/Analysis/InstructionSimplify.h
+++ b/include/llvm/Analysis/InstructionSimplify.h
@@ -70,174 +70,173 @@ struct SimplifyQuery {
Copy.CxtI = I;
return Copy;
}
- };
+};
- // NOTE: the explicit multiple argument versions of these functions are
- // deprecated.
- // Please use the SimplifyQuery versions in new code.
+// NOTE: the explicit multiple argument versions of these functions are
+// deprecated.
+// Please use the SimplifyQuery versions in new code.
- /// Given operands for an Add, fold the result or return null.
- Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
+/// Given operands for an Add, fold the result or return null.
+Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
const SimplifyQuery &Q);
- /// Given operands for a Sub, fold the result or return null.
- Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
- const SimplifyQuery &Q);
+/// Given operands for a Sub, fold the result or return null.
+Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
+ const SimplifyQuery &Q);
- /// Given operands for an FAdd, fold the result or return null.
- Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
- const SimplifyQuery &Q);
+/// Given operands for an FAdd, fold the result or return null.
+Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+ const SimplifyQuery &Q);
- /// Given operands for an FSub, fold the result or return null.
- Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
- const SimplifyQuery &Q);
+/// Given operands for an FSub, fold the result or return null.
+Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+ const SimplifyQuery &Q);
- /// Given operands for an FMul, fold the result or return null.
- Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
- const SimplifyQuery &Q);
+/// Given operands for an FMul, fold the result or return null.
+Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+ const SimplifyQuery &Q);
- /// Given operands for a Mul, fold the result or return null.
- Value *SimplifyMulInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for a Mul, fold the result or return null.
+Value *SimplifyMulInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for an SDiv, fold the result or return null.
- Value *SimplifySDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for an SDiv, fold the result or return null.
+Value *SimplifySDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for a UDiv, fold the result or return null.
- Value *SimplifyUDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for a UDiv, fold the result or return null.
+Value *SimplifyUDivInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for an FDiv, fold the result or return null.
- Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
- const SimplifyQuery &Q);
+/// Given operands for an FDiv, fold the result or return null.
+Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+ const SimplifyQuery &Q);
- /// Given operands for an SRem, fold the result or return null.
- Value *SimplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for an SRem, fold the result or return null.
+Value *SimplifySRemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for a URem, fold the result or return null.
- Value *SimplifyURemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for a URem, fold the result or return null.
+Value *SimplifyURemInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for an FRem, fold the result or return null.
- Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
- const SimplifyQuery &Q);
-
- /// Given operands for a Shl, fold the result or return null.
- Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
- const SimplifyQuery &Q);
-
- /// Given operands for a LShr, fold the result or return null.
- Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
- const SimplifyQuery &Q);
+/// Given operands for an FRem, fold the result or return null.
+Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF,
+ const SimplifyQuery &Q);
- /// Given operands for a AShr, fold the result or return nulll.
- Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
- const SimplifyQuery &Q);
+/// Given operands for a Shl, fold the result or return null.
+Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
+ const SimplifyQuery &Q);
- /// Given operands for an And, fold the result or return null.
- Value *SimplifyAndInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for a LShr, fold the result or return null.
+Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
+ const SimplifyQuery &Q);
- /// Given operands for an Or, fold the result or return null.
- Value *SimplifyOrInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for a AShr, fold the result or return nulll.
+Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
+ const SimplifyQuery &Q);
- /// Given operands for an Xor, fold the result or return null.
- Value *SimplifyXorInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
+/// Given operands for an And, fold the result or return null.
+Value *SimplifyAndInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for an ICmpInst, fold the result or return null.
- Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
- const SimplifyQuery &Q);
+/// Given operands for an Or, fold the result or return null.
+Value *SimplifyOrInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for an FCmpInst, fold the result or return null.
- Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
- FastMathFlags FMF, const SimplifyQuery &Q);
+/// Given operands for an Xor, fold the result or return null.
+Value *SimplifyXorInst(Value *LHS, Value *RHS, const SimplifyQuery &Q);
- /// Given operands for a SelectInst, fold the result or return null.
- Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
- const SimplifyQuery &Q);
+/// Given operands for an ICmpInst, fold the result or return null.
+Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
+ const SimplifyQuery &Q);
- /// Given operands for a GetElementPtrInst, fold the result or return null.
- Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
- const SimplifyQuery &Q);
+/// Given operands for an FCmpInst, fold the result or return null.
+Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
+ FastMathFlags FMF, const SimplifyQuery &Q);
- /// Given operands for an InsertValueInst, fold the result or return null.
- Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
- ArrayRef<unsigned> Idxs,
- const SimplifyQuery &Q);
+/// Given operands for a SelectInst, fold the result or return null.
+Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal,
+ const SimplifyQuery &Q);
- /// Given operands for an ExtractValueInst, fold the result or return null.
- Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
- const SimplifyQuery &Q);
+/// Given operands for a GetElementPtrInst, fold the result or return null.
+Value *SimplifyGEPInst(Type *SrcTy, ArrayRef<Value *> Ops,
+ const SimplifyQuery &Q);
- /// Given operands for an ExtractElementInst, fold the result or return null.
- Value *SimplifyExtractElementInst(Value *Vec, Value *Idx,
- const SimplifyQuery &Q);
+/// Given operands for an InsertValueInst, fold the result or return null.
+Value *SimplifyInsertValueInst(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
+ const SimplifyQuery &Q);
- /// Given operands for a CastInst, fold the result or return null.
- Value *SimplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
- const SimplifyQuery &Q);
+/// Given operands for an ExtractValueInst, fold the result or return null.
+Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
+ const SimplifyQuery &Q);
- /// Given operands for a ShuffleVectorInst, fold the result or return null.
- Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
- Type *RetTy, const SimplifyQuery &Q);
+/// Given operands for an ExtractElementInst, fold the result or return null.
+Value *SimplifyExtractElementInst(Value *Vec, Value *Idx,
+ const SimplifyQuery &Q);
- //=== Helper functions for higher up the class hierarchy.
+/// Given operands for a CastInst, fold the result or return null.
+Value *SimplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
+ const SimplifyQuery &Q);
+/// Given operands for a ShuffleVectorInst, fold the result or return null.
+Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
+ Type *RetTy, const SimplifyQuery &Q);
- /// Given operands for a CmpInst, fold the result or return null.
- Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
- const SimplifyQuery &Q);
+//=== Helper functions for higher up the class hierarchy.
- /// Given operands for a BinaryOperator, fold the result or return null.
- Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
+/// Given operands for a CmpInst, fold the result or return null.
+Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const SimplifyQuery &Q);
- /// Given operands for an FP BinaryOperator, fold the result or return null.
- /// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
- /// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
- Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
- FastMathFlags FMF, const SimplifyQuery &Q);
-
- /// Given a function and iterators over arguments, fold the result or return
- /// null.
- Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
- User::op_iterator ArgEnd, const SimplifyQuery &Q);
-
- /// Given a function and set of arguments, fold the result or return null.
- Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const SimplifyQuery &Q);
-
- /// See if we can compute a simplified version of this instruction. If not,
- /// return null.
- Value *SimplifyInstruction(Instruction *I, const SimplifyQuery &Q,
- OptimizationRemarkEmitter *ORE = nullptr);
-
- /// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively.
- ///
- /// This first performs a normal RAUW of I with SimpleV. It then recursively
- /// attempts to simplify those users updated by the operation. The 'I'
- /// instruction must not be equal to the simplified value 'SimpleV'.
- ///
- /// The function returns true if any simplifications were performed.
- bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
- const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr,
- AssumptionCache *AC = nullptr);
-
- /// Recursively attempt to simplify an instruction.
- ///
- /// This routine uses SimplifyInstruction to simplify 'I', and if successful
- /// replaces uses of 'I' with the simplified value. It then recurses on each
- /// of the users impacted. It returns true if any simplifications were
- /// performed.
- bool recursivelySimplifyInstruction(Instruction *I,
- const TargetLibraryInfo *TLI = nullptr,
- const DominatorTree *DT = nullptr,
- AssumptionCache *AC = nullptr);
- // These helper functions return a SimplifyQuery structure that contains as
- // many of the optional analysis we use as are currently valid. This is the
- // strongly preferred way of constructing SimplifyQuery in passes.
- const SimplifyQuery getBestSimplifyQuery(Pass &, Function &);
- template <class T, class... TArgs>
- const SimplifyQuery getBestSimplifyQuery(AnalysisManager<T, TArgs...> &,
- Function &);
- const SimplifyQuery getBestSimplifyQuery(LoopStandardAnalysisResults &,
- const DataLayout &);
+/// Given operands for a BinaryOperator, fold the result or return null.
+Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
+ const SimplifyQuery &Q);
+
+/// Given operands for an FP BinaryOperator, fold the result or return null.
+/// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the
+/// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp.
+Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS,
+ FastMathFlags FMF, const SimplifyQuery &Q);
+
+/// Given a function and iterators over arguments, fold the result or return
+/// null.
+Value *SimplifyCall(Value *V, User::op_iterator ArgBegin,
+ User::op_iterator ArgEnd, const SimplifyQuery &Q);
+
+/// Given a function and set of arguments, fold the result or return null.
+Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const SimplifyQuery &Q);
+
+/// See if we can compute a simplified version of this instruction. If not,
+/// return null.
+Value *SimplifyInstruction(Instruction *I, const SimplifyQuery &Q,
+ OptimizationRemarkEmitter *ORE = nullptr);
+
+/// Replace all uses of 'I' with 'SimpleV' and simplify the uses recursively.
+///
+/// This first performs a normal RAUW of I with SimpleV. It then recursively
+/// attempts to simplify those users updated by the operation. The 'I'
+/// instruction must not be equal to the simplified value 'SimpleV'.
+///
+/// The function returns true if any simplifications were performed.
+bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV,
+ const TargetLibraryInfo *TLI = nullptr,
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr);
+
+/// Recursively attempt to simplify an instruction.
+///
+/// This routine uses SimplifyInstruction to simplify 'I', and if successful
+/// replaces uses of 'I' with the simplified value. It then recurses on each
+/// of the users impacted. It returns true if any simplifications were
+/// performed.
+bool recursivelySimplifyInstruction(Instruction *I,
+ const TargetLibraryInfo *TLI = nullptr,
+ const DominatorTree *DT = nullptr,
+ AssumptionCache *AC = nullptr);
+
+// These helper functions return a SimplifyQuery structure that contains as
+// many of the optional analysis we use as are currently valid. This is the
+// strongly preferred way of constructing SimplifyQuery in passes.
+const SimplifyQuery getBestSimplifyQuery(Pass &, Function &);
+template <class T, class... TArgs>
+const SimplifyQuery getBestSimplifyQuery(AnalysisManager<T, TArgs...> &,
+ Function &);
+const SimplifyQuery getBestSimplifyQuery(LoopStandardAnalysisResults &,
+ const DataLayout &);
} // end namespace llvm
#endif
diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h
index 496ae189e57b..75e7688bbdc2 100644
--- a/include/llvm/Analysis/LoopPass.h
+++ b/include/llvm/Analysis/LoopPass.h
@@ -126,9 +126,8 @@ public:
}
public:
- // Add a new loop into the loop queue as a child of the given parent, or at
- // the top level if \c ParentLoop is null.
- Loop &addLoop(Loop *ParentLoop);
+ // Add a new loop into the loop queue.
+ void addLoop(Loop &L);
//===--------------------------------------------------------------------===//
/// SimpleAnalysis - Provides simple interface to update analysis info
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index ac54bd4cfffb..4a6fc245c225 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -1533,6 +1533,12 @@ public:
/// specified loop.
bool isLoopInvariant(const SCEV *S, const Loop *L);
+ /// Determine if the SCEV can be evaluated at loop's entry. It is true if it
+ /// doesn't depend on a SCEVUnknown of an instruction which is dominated by
+ /// the header of loop L.
+ bool isAvailableAtLoopEntry(const SCEV *S, const Loop *L, DominatorTree &DT,
+ LoopInfo &LI);
+
/// Return true if the given SCEV changes value in a known way in the
/// specified loop. This property being true implies that the value is
/// variant in the loop AND that we can emit an expression to compute the
diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h
index 0a0af384c3e6..6cbe3a1f515e 100644
--- a/include/llvm/Analysis/TargetTransformInfo.h
+++ b/include/llvm/Analysis/TargetTransformInfo.h
@@ -396,6 +396,9 @@ public:
bool isLegalMaskedScatter(Type *DataType) const;
bool isLegalMaskedGather(Type *DataType) const;
+ /// Return true if target doesn't mind addresses in vectors.
+ bool prefersVectorizedAddressing() const;
+
/// \brief Return the cost of the scaling factor used in the addressing
/// mode represented by AM for this target, for a load/store
/// of the specified type.
@@ -807,6 +810,7 @@ public:
virtual bool isLegalMaskedLoad(Type *DataType) = 0;
virtual bool isLegalMaskedScatter(Type *DataType) = 0;
virtual bool isLegalMaskedGather(Type *DataType) = 0;
+ virtual bool prefersVectorizedAddressing() = 0;
virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset, bool HasBaseReg,
int64_t Scale, unsigned AddrSpace) = 0;
@@ -1000,6 +1004,9 @@ public:
bool isLegalMaskedGather(Type *DataType) override {
return Impl.isLegalMaskedGather(DataType);
}
+ bool prefersVectorizedAddressing() override {
+ return Impl.prefersVectorizedAddressing();
+ }
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale,
unsigned AddrSpace) override {
diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h
index 550e84ad90c4..ad1a7cb748fe 100644
--- a/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -237,6 +237,8 @@ public:
bool isLegalMaskedGather(Type *DataType) { return false; }
+ bool prefersVectorizedAddressing() { return true; }
+
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
bool HasBaseReg, int64_t Scale, unsigned AddrSpace) {
// Guess that all legal addressing mode are free.
diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h
index cf24062e46f8..b1ee76159c4b 100644
--- a/include/llvm/Analysis/ValueTracking.h
+++ b/include/llvm/Analysis/ValueTracking.h
@@ -60,7 +60,8 @@ template <typename T> class ArrayRef;
KnownBits computeKnownBits(const Value *V, const DataLayout &DL,
unsigned Depth = 0, AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
- const DominatorTree *DT = nullptr);
+ const DominatorTree *DT = nullptr,
+ OptimizationRemarkEmitter *ORE = nullptr);
/// Compute known bits from the range metadata.
/// \p KnownZero the set of bits that are known to be zero
/// \p KnownOne the set of bits that are known to be one
diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h
index 180c0b579248..c898667f1474 100644
--- a/include/llvm/CodeGen/AsmPrinter.h
+++ b/include/llvm/CodeGen/AsmPrinter.h
@@ -34,6 +34,7 @@
namespace llvm {
class AsmPrinterHandler;
+class BasicBlock;
class BlockAddress;
class Constant;
class ConstantArray;
@@ -43,6 +44,7 @@ class DIEAbbrev;
class DwarfDebug;
class GCMetadataPrinter;
class GlobalIndirectSymbol;
+class GlobalObject;
class GlobalValue;
class GlobalVariable;
class GCStrategy;
@@ -65,6 +67,8 @@ class MCSubtargetInfo;
class MCSymbol;
class MCTargetOptions;
class MDNode;
+class Module;
+class raw_ostream;
class TargetLoweringObjectFile;
class TargetMachine;
@@ -109,7 +113,7 @@ public:
/// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of
/// its number of uses by other globals.
- typedef std::pair<const GlobalVariable *, unsigned> GOTEquivUsePair;
+ using GOTEquivUsePair = std::pair<const GlobalVariable *, unsigned>;
MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs;
/// Enable print [latency:throughput] in output
diff --git a/include/llvm/CodeGen/AtomicExpandUtils.h b/include/llvm/CodeGen/AtomicExpandUtils.h
index ac18eac8a1ce..1f9c96b18e1b 100644
--- a/include/llvm/CodeGen/AtomicExpandUtils.h
+++ b/include/llvm/CodeGen/AtomicExpandUtils.h
@@ -1,4 +1,4 @@
-//===-- AtomicExpandUtils.h - Utilities for expanding atomic instructions -===//
+//===- AtomicExpandUtils.h - Utilities for expanding atomic instructions --===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,19 +7,24 @@
//
//===----------------------------------------------------------------------===//
+#ifndef LLVM_CODEGEN_ATOMICEXPANDUTILS_H
+#define LLVM_CODEGEN_ATOMICEXPANDUTILS_H
+
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/Support/AtomicOrdering.h"
namespace llvm {
-class Value;
-class AtomicRMWInst;
+class AtomicRMWInst;
+class Value;
/// Parameters (see the expansion example below):
/// (the builder, %addr, %loaded, %new_val, ordering,
/// /* OUT */ %success, /* OUT */ %new_loaded)
-typedef function_ref<void(IRBuilder<> &, Value *, Value *, Value *,
- AtomicOrdering, Value *&, Value *&)> CreateCmpXchgInstFun;
+using CreateCmpXchgInstFun =
+ function_ref<void(IRBuilder<> &, Value *, Value *, Value *, AtomicOrdering,
+ Value *&, Value *&)>;
/// \brief Expand an atomic RMW instruction into a loop utilizing
/// cmpxchg. You'll want to make sure your target machine likes cmpxchg
@@ -42,7 +47,8 @@ typedef function_ref<void(IRBuilder<> &, Value *, Value *, Value *,
/// loop:
/// %loaded = phi iN [ %init_loaded, %entry ], [ %new_loaded, %loop ]
/// %new = some_op iN %loaded, %incr
-/// ; This is what -atomic-expand will produce using this function on i686 targets:
+/// ; This is what -atomic-expand will produce using this function on i686
+/// targets:
/// %pair = cmpxchg iN* %addr, iN %loaded, iN %new_val
/// %new_loaded = extractvalue { iN, i1 } %pair, 0
/// %success = extractvalue { iN, i1 } %pair, 1
@@ -52,6 +58,8 @@ typedef function_ref<void(IRBuilder<> &, Value *, Value *, Value *,
/// [...]
///
/// Returns true if the containing function was modified.
-bool
-expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun Factory);
-}
+bool expandAtomicRMWToCmpXchg(AtomicRMWInst *AI, CreateCmpXchgInstFun Factory);
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_ATOMICEXPANDUTILS_H
diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h
index a40147336fe2..4be44e62fa92 100644
--- a/include/llvm/CodeGen/DIE.h
+++ b/include/llvm/CodeGen/DIE.h
@@ -1,4 +1,4 @@
-//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===//
+//===- lib/CodeGen/DIE.h - DWARF Info Entries -------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -31,6 +31,7 @@
#include <iterator>
#include <new>
#include <type_traits>
+#include <utility>
#include <vector>
namespace llvm {
@@ -53,11 +54,11 @@ class DIEAbbrevData {
dwarf::Form Form;
/// Dwarf attribute value for DW_FORM_implicit_const
- int64_t Value;
+ int64_t Value = 0;
public:
DIEAbbrevData(dwarf::Attribute A, dwarf::Form F)
- : Attribute(A), Form(F), Value(0) {}
+ : Attribute(A), Form(F) {}
DIEAbbrevData(dwarf::Attribute A, int64_t V)
: Attribute(A), Form(dwarf::DW_FORM_implicit_const), Value(V) {}
@@ -136,13 +137,14 @@ class DIEAbbrevSet {
/// storage container.
BumpPtrAllocator &Alloc;
/// \brief FoldingSet that uniques the abbreviations.
- llvm::FoldingSet<DIEAbbrev> AbbreviationsSet;
+ FoldingSet<DIEAbbrev> AbbreviationsSet;
/// A list of all the unique abbreviations in use.
std::vector<DIEAbbrev *> Abbreviations;
public:
DIEAbbrevSet(BumpPtrAllocator &A) : Alloc(A) {}
~DIEAbbrevSet();
+
/// Generate the abbreviation declaration for a DIE and return a pointer to
/// the generated abbreviation.
///
@@ -289,13 +291,11 @@ public:
/// A pointer to another debug information entry. An instance of this class can
/// also be used as a proxy for a debug information entry not yet defined
/// (ie. types.)
-class DIE;
class DIEEntry {
DIE *Entry;
- DIEEntry() = delete;
-
public:
+ DIEEntry() = delete;
explicit DIEEntry(DIE &E) : Entry(&E) {}
DIE &getEntry() const { return *Entry; }
@@ -348,10 +348,10 @@ private:
///
/// All values that aren't standard layout (or are larger than 8 bytes)
/// should be stored by reference instead of by value.
- typedef AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel,
- DIEDelta *, DIEEntry, DIEBlock *, DIELoc *,
- DIELocList>
- ValTy;
+ using ValTy = AlignedCharArrayUnion<DIEInteger, DIEString, DIEExpr, DIELabel,
+ DIEDelta *, DIEEntry, DIEBlock *,
+ DIELoc *, DIELocList>;
+
static_assert(sizeof(ValTy) <= sizeof(uint64_t) ||
sizeof(ValTy) <= sizeof(void *),
"Expected all large types to be stored via pointer");
@@ -486,10 +486,12 @@ struct IntrusiveBackListNode {
};
struct IntrusiveBackListBase {
- typedef IntrusiveBackListNode Node;
+ using Node = IntrusiveBackListNode;
+
Node *Last = nullptr;
bool empty() const { return !Last; }
+
void push_back(Node &N) {
assert(N.Next.getPointer() == &N && "Expected unlinked node");
assert(N.Next.getInt() == true && "Expected unlinked node");
@@ -505,6 +507,7 @@ struct IntrusiveBackListBase {
template <class T> class IntrusiveBackList : IntrusiveBackListBase {
public:
using IntrusiveBackListBase::empty;
+
void push_back(T &N) { IntrusiveBackListBase::push_back(N); }
T &back() { return *static_cast<T *>(Last); }
const T &back() const { return *static_cast<T *>(Last); }
@@ -513,6 +516,7 @@ public:
class iterator
: public iterator_facade_base<iterator, std::forward_iterator_tag, T> {
friend class const_iterator;
+
Node *N = nullptr;
public:
@@ -585,10 +589,12 @@ public:
class DIEValueList {
struct Node : IntrusiveBackListNode {
DIEValue V;
+
explicit Node(DIEValue V) : V(V) {}
};
- typedef IntrusiveBackList<Node> ListTy;
+ using ListTy = IntrusiveBackList<Node>;
+
ListTy List;
public:
@@ -597,9 +603,10 @@ public:
: public iterator_adaptor_base<value_iterator, ListTy::iterator,
std::forward_iterator_tag, DIEValue> {
friend class const_value_iterator;
- typedef iterator_adaptor_base<value_iterator, ListTy::iterator,
- std::forward_iterator_tag,
- DIEValue> iterator_adaptor;
+
+ using iterator_adaptor =
+ iterator_adaptor_base<value_iterator, ListTy::iterator,
+ std::forward_iterator_tag, DIEValue>;
public:
value_iterator() = default;
@@ -612,9 +619,9 @@ public:
class const_value_iterator : public iterator_adaptor_base<
const_value_iterator, ListTy::const_iterator,
std::forward_iterator_tag, const DIEValue> {
- typedef iterator_adaptor_base<const_value_iterator, ListTy::const_iterator,
- std::forward_iterator_tag,
- const DIEValue> iterator_adaptor;
+ using iterator_adaptor =
+ iterator_adaptor_base<const_value_iterator, ListTy::const_iterator,
+ std::forward_iterator_tag, const DIEValue>;
public:
const_value_iterator() = default;
@@ -627,8 +634,8 @@ public:
const DIEValue &operator*() const { return wrapped()->V; }
};
- typedef iterator_range<value_iterator> value_range;
- typedef iterator_range<const_value_iterator> const_value_range;
+ using value_range = iterator_range<value_iterator>;
+ using const_value_range = iterator_range<const_value_iterator>;
value_iterator addValue(BumpPtrAllocator &Alloc, const DIEValue &V) {
List.push_back(*new (Alloc) Node(V));
@@ -657,15 +664,15 @@ class DIE : IntrusiveBackListNode, public DIEValueList {
friend class DIEUnit;
/// Dwarf unit relative offset.
- unsigned Offset;
+ unsigned Offset = 0;
/// Size of instance + children.
- unsigned Size;
+ unsigned Size = 0;
unsigned AbbrevNumber = ~0u;
/// Dwarf tag code.
dwarf::Tag Tag = (dwarf::Tag)0;
/// Set to true to force a DIE to emit an abbreviation that says it has
/// children even when it doesn't. This is used for unit testing purposes.
- bool ForceChildren;
+ bool ForceChildren = false;
/// Children DIEs.
IntrusiveBackList<DIE> Children;
@@ -673,20 +680,19 @@ class DIE : IntrusiveBackListNode, public DIEValueList {
/// DIEUnit which contains this DIE as its unit DIE.
PointerUnion<DIE *, DIEUnit *> Owner;
- DIE() = delete;
- explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Tag(Tag),
- ForceChildren(false) {}
+ explicit DIE(dwarf::Tag Tag) : Tag(Tag) {}
public:
+ DIE() = delete;
+ DIE(const DIE &RHS) = delete;
+ DIE(DIE &&RHS) = delete;
+ DIE &operator=(const DIE &RHS) = delete;
+ DIE &operator=(const DIE &&RHS) = delete;
+
static DIE *get(BumpPtrAllocator &Alloc, dwarf::Tag Tag) {
return new (Alloc) DIE(Tag);
}
- DIE(const DIE &RHS) = delete;
- DIE(DIE &&RHS) = delete;
- void operator=(const DIE &RHS) = delete;
- void operator=(const DIE &&RHS) = delete;
-
// Accessors.
unsigned getAbbrevNumber() const { return AbbrevNumber; }
dwarf::Tag getTag() const { return Tag; }
@@ -696,10 +702,10 @@ public:
bool hasChildren() const { return ForceChildren || !Children.empty(); }
void setForceChildren(bool B) { ForceChildren = B; }
- typedef IntrusiveBackList<DIE>::iterator child_iterator;
- typedef IntrusiveBackList<DIE>::const_iterator const_child_iterator;
- typedef iterator_range<child_iterator> child_range;
- typedef iterator_range<const_child_iterator> const_child_range;
+ using child_iterator = IntrusiveBackList<DIE>::iterator;
+ using const_child_iterator = IntrusiveBackList<DIE>::const_iterator;
+ using child_range = iterator_range<child_iterator>;
+ using const_child_range = iterator_range<const_child_iterator>;
child_range children() {
return make_range(Children.begin(), Children.end());
@@ -838,10 +844,10 @@ struct BasicDIEUnit final : DIEUnit {
/// DIELoc - Represents an expression location.
//
class DIELoc : public DIEValueList {
- mutable unsigned Size; // Size in bytes excluding size header.
+ mutable unsigned Size = 0; // Size in bytes excluding size header.
public:
- DIELoc() : Size(0) {}
+ DIELoc() = default;
/// ComputeSize - Calculate the size of the location expression.
///
@@ -872,10 +878,10 @@ public:
/// DIEBlock - Represents a block of values.
//
class DIEBlock : public DIEValueList {
- mutable unsigned Size; // Size in bytes excluding size header.
+ mutable unsigned Size = 0; // Size in bytes excluding size header.
public:
- DIEBlock() : Size(0) {}
+ DIEBlock() = default;
/// ComputeSize - Calculate the size of the location expression.
///
diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h
index 0f0005b83c54..98ff526dfe94 100644
--- a/include/llvm/CodeGen/FaultMaps.h
+++ b/include/llvm/CodeGen/FaultMaps.h
@@ -56,7 +56,7 @@ private:
HandlerOffsetExpr(HandlerOffset) {}
};
- typedef std::vector<FaultInfo> FunctionFaultInfos;
+ using FunctionFaultInfos = std::vector<FaultInfo>;
// We'd like to keep a stable iteration order for FunctionInfos to help
// FileCheck based testing.
@@ -78,20 +78,17 @@ private:
/// generated by the version of LLVM that includes it. No guarantees are made
/// with respect to forward or backward compatibility.
class FaultMapParser {
- typedef uint8_t FaultMapVersionType;
- static const size_t FaultMapVersionOffset = 0;
+ using FaultMapVersionType = uint8_t;
+ using Reserved0Type = uint8_t;
+ using Reserved1Type = uint16_t;
+ using NumFunctionsType = uint32_t;
- typedef uint8_t Reserved0Type;
+ static const size_t FaultMapVersionOffset = 0;
static const size_t Reserved0Offset =
FaultMapVersionOffset + sizeof(FaultMapVersionType);
-
- typedef uint16_t Reserved1Type;
static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type);
-
- typedef uint32_t NumFunctionsType;
static const size_t NumFunctionsOffset =
Reserved1Offset + sizeof(Reserved1Type);
-
static const size_t FunctionInfosOffset =
NumFunctionsOffset + sizeof(NumFunctionsType);
@@ -105,14 +102,13 @@ class FaultMapParser {
public:
class FunctionFaultInfoAccessor {
- typedef uint32_t FaultKindType;
- static const size_t FaultKindOffset = 0;
+ using FaultKindType = uint32_t;
+ using FaultingPCOffsetType = uint32_t;
+ using HandlerPCOffsetType = uint32_t;
- typedef uint32_t FaultingPCOffsetType;
+ static const size_t FaultKindOffset = 0;
static const size_t FaultingPCOffsetOffset =
FaultKindOffset + sizeof(FaultKindType);
-
- typedef uint32_t HandlerPCOffsetType;
static const size_t HandlerPCOffsetOffset =
FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType);
@@ -140,20 +136,17 @@ public:
};
class FunctionInfoAccessor {
- typedef uint64_t FunctionAddrType;
- static const size_t FunctionAddrOffset = 0;
+ using FunctionAddrType = uint64_t;
+ using NumFaultingPCsType = uint32_t;
+ using ReservedType = uint32_t;
- typedef uint32_t NumFaultingPCsType;
+ static const size_t FunctionAddrOffset = 0;
static const size_t NumFaultingPCsOffset =
FunctionAddrOffset + sizeof(FunctionAddrType);
-
- typedef uint32_t ReservedType;
static const size_t ReservedOffset =
NumFaultingPCsOffset + sizeof(NumFaultingPCsType);
-
static const size_t FunctionFaultInfosOffset =
ReservedOffset + sizeof(ReservedType);
-
static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset;
const uint8_t *P = nullptr;
diff --git a/include/llvm/CodeGen/GlobalISel/Localizer.h b/include/llvm/CodeGen/GlobalISel/Localizer.h
new file mode 100644
index 000000000000..0a46eb9e7840
--- /dev/null
+++ b/include/llvm/CodeGen/GlobalISel/Localizer.h
@@ -0,0 +1,78 @@
+//== llvm/CodeGen/GlobalISel/Localizer.h - Localizer -------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file describes the interface of the Localizer pass.
+/// This pass moves/duplicates constant-like instructions close to their uses.
+/// Its primarily goal is to workaround the deficiencies of the fast register
+/// allocator.
+/// With GlobalISel constants are all materialized in the entry block of
+/// a function. However, the fast allocator cannot rematerialize constants and
+/// has a lot more live-ranges to deal with and will most likely end up
+/// spilling a lot.
+/// By pushing the constants close to their use, we only create small
+/// live-ranges.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H
+#define LLVM_CODEGEN_GLOBALISEL_LOCALIZER_H
+
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+// Forward declarations.
+class MachineRegisterInfo;
+
+/// This pass implements the localization mechanism described at the
+/// top of this file. One specificity of the implementation is that
+/// it will materialize one and only one instance of a constant per
+/// basic block, thus enabling reuse of that constant within that block.
+/// Moreover, it only materializes constants in blocks where they
+/// are used. PHI uses are considered happening at the end of the
+/// related predecessor.
+class Localizer : public MachineFunctionPass {
+public:
+ static char ID;
+
+private:
+ /// MRI contains all the register class/bank information that this
+ /// pass uses and updates.
+ MachineRegisterInfo *MRI;
+
+ /// Check whether or not \p MI needs to be moved close to its uses.
+ static bool shouldLocalize(const MachineInstr &MI);
+
+ /// Check if \p MOUse is used in the same basic block as \p Def.
+ /// If the use is in the same block, we say it is local.
+ /// When the use is not local, \p InsertMBB will contain the basic
+ /// block when to insert \p Def to have a local use.
+ static bool isLocalUse(MachineOperand &MOUse, const MachineInstr &Def,
+ MachineBasicBlock *&InsertMBB);
+
+ /// Initialize the field members using \p MF.
+ void init(MachineFunction &MF);
+
+public:
+ Localizer();
+
+ StringRef getPassName() const override { return "Localizer"; }
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties()
+ .set(MachineFunctionProperties::Property::IsSSA)
+ .set(MachineFunctionProperties::Property::Legalized)
+ .set(MachineFunctionProperties::Property::RegBankSelected);
+ }
+
+ bool runOnMachineFunction(MachineFunction &MF) override;
+};
+
+} // End namespace llvm.
+
+#endif
diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h
index f2a9a9f73ca6..2300a106c358 100644
--- a/include/llvm/CodeGen/ISDOpcodes.h
+++ b/include/llvm/CodeGen/ISDOpcodes.h
@@ -264,6 +264,14 @@ namespace ISD {
/// optimized.
STRICT_FADD, STRICT_FSUB, STRICT_FMUL, STRICT_FDIV, STRICT_FREM,
+ /// Constrained versions of libm-equivalent floating point intrinsics.
+ /// These will be lowered to the equivalent non-constrained pseudo-op
+ /// (or expanded to the equivalent library call) before final selection.
+ /// They are used to limit optimizations while the DAG is being optimized.
+ STRICT_FSQRT, STRICT_FPOW, STRICT_FPOWI, STRICT_FSIN, STRICT_FCOS,
+ STRICT_FEXP, STRICT_FEXP2, STRICT_FLOG, STRICT_FLOG10, STRICT_FLOG2,
+ STRICT_FRINT, STRICT_FNEARBYINT,
+
/// FMA - Perform a * b + c with no intermediate rounding step.
FMA,
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index b792cba4b78a..40cd146f88f8 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/LiveInterval.h - Interval representation ---*- C++ -*-===//
+//===- llvm/CodeGen/LiveInterval.h - Interval representation ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -21,22 +21,30 @@
#ifndef LLVM_CODEGEN_LIVEINTERVAL_H
#define LLVM_CODEGEN_LIVEINTERVAL_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IntEqClasses.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/SlotIndexes.h"
+#include "llvm/MC/LaneBitmask.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Support/MathExtras.h"
+#include <algorithm>
#include <cassert>
-#include <climits>
+#include <cstddef>
+#include <functional>
+#include <memory>
#include <set>
+#include <tuple>
+#include <utility>
namespace llvm {
+
class CoalescerPair;
class LiveIntervals;
- class MachineInstr;
class MachineRegisterInfo;
- class TargetRegisterInfo;
class raw_ostream;
- template <typename T, unsigned Small> class SmallPtrSet;
/// VNInfo - Value Number Information.
/// This class holds information about a machine level values, including
@@ -44,7 +52,7 @@ namespace llvm {
///
class VNInfo {
public:
- typedef BumpPtrAllocator Allocator;
+ using Allocator = BumpPtrAllocator;
/// The ID number of this value.
unsigned id;
@@ -53,14 +61,10 @@ namespace llvm {
SlotIndex def;
/// VNInfo constructor.
- VNInfo(unsigned i, SlotIndex d)
- : id(i), def(d)
- { }
+ VNInfo(unsigned i, SlotIndex d) : id(i), def(d) {}
/// VNInfo constructor, copies values from orig, except for the value number.
- VNInfo(unsigned i, const VNInfo &orig)
- : id(i), def(orig.def)
- { }
+ VNInfo(unsigned i, const VNInfo &orig) : id(i), def(orig.def) {}
/// Copy from the parameter into this VNInfo.
void copyFrom(VNInfo &src) {
@@ -152,16 +156,16 @@ namespace llvm {
/// segment with a new value number is used.
class LiveRange {
public:
-
/// This represents a simple continuous liveness interval for a value.
/// The start point is inclusive, the end point exclusive. These intervals
/// are rendered as [start,end).
struct Segment {
SlotIndex start; // Start point of the interval (inclusive)
SlotIndex end; // End point of the interval (exclusive)
- VNInfo *valno; // identifier for the value contained in this segment.
+ VNInfo *valno = nullptr; // identifier for the value contained in this
+ // segment.
- Segment() : valno(nullptr) {}
+ Segment() = default;
Segment(SlotIndex S, SlotIndex E, VNInfo *V)
: start(S), end(E), valno(V) {
@@ -189,8 +193,8 @@ namespace llvm {
void dump() const;
};
- typedef SmallVector<Segment, 2> Segments;
- typedef SmallVector<VNInfo *, 2> VNInfoList;
+ using Segments = SmallVector<Segment, 2>;
+ using VNInfoList = SmallVector<VNInfo *, 2>;
Segments segments; // the liveness segments
VNInfoList valnos; // value#'s
@@ -198,22 +202,24 @@ namespace llvm {
// The segment set is used temporarily to accelerate initial computation
// of live ranges of physical registers in computeRegUnitRange.
// After that the set is flushed to the segment vector and deleted.
- typedef std::set<Segment> SegmentSet;
+ using SegmentSet = std::set<Segment>;
std::unique_ptr<SegmentSet> segmentSet;
- typedef Segments::iterator iterator;
+ using iterator = Segments::iterator;
+ using const_iterator = Segments::const_iterator;
+
iterator begin() { return segments.begin(); }
iterator end() { return segments.end(); }
- typedef Segments::const_iterator const_iterator;
const_iterator begin() const { return segments.begin(); }
const_iterator end() const { return segments.end(); }
- typedef VNInfoList::iterator vni_iterator;
+ using vni_iterator = VNInfoList::iterator;
+ using const_vni_iterator = VNInfoList::const_iterator;
+
vni_iterator vni_begin() { return valnos.begin(); }
vni_iterator vni_end() { return valnos.end(); }
- typedef VNInfoList::const_iterator const_vni_iterator;
const_vni_iterator vni_begin() const { return valnos.begin(); }
const_vni_iterator vni_end() const { return valnos.end(); }
@@ -631,40 +637,37 @@ namespace llvm {
/// or stack slot.
class LiveInterval : public LiveRange {
public:
- typedef LiveRange super;
+ using super = LiveRange;
/// A live range for subregisters. The LaneMask specifies which parts of the
/// super register are covered by the interval.
/// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()).
class SubRange : public LiveRange {
public:
- SubRange *Next;
+ SubRange *Next = nullptr;
LaneBitmask LaneMask;
/// Constructs a new SubRange object.
- SubRange(LaneBitmask LaneMask)
- : Next(nullptr), LaneMask(LaneMask) {
- }
+ SubRange(LaneBitmask LaneMask) : LaneMask(LaneMask) {}
/// Constructs a new SubRange object by copying liveness from @p Other.
SubRange(LaneBitmask LaneMask, const LiveRange &Other,
BumpPtrAllocator &Allocator)
- : LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) {
- }
+ : LiveRange(Other, Allocator), LaneMask(LaneMask) {}
void print(raw_ostream &OS) const;
void dump() const;
};
private:
- SubRange *SubRanges; ///< Single linked list of subregister live ranges.
+ SubRange *SubRanges = nullptr; ///< Single linked list of subregister live
+ /// ranges.
public:
const unsigned reg; // the register or stack slot of this interval.
float weight; // weight of this interval
- LiveInterval(unsigned Reg, float Weight)
- : SubRanges(nullptr), reg(Reg), weight(Weight) {}
+ LiveInterval(unsigned Reg, float Weight) : reg(Reg), weight(Weight) {}
~LiveInterval() {
clearSubRanges();
@@ -673,8 +676,10 @@ namespace llvm {
template<typename T>
class SingleLinkedListIterator {
T *P;
+
public:
SingleLinkedListIterator<T>(T *P) : P(P) {}
+
SingleLinkedListIterator<T> &operator++() {
P = P->Next;
return *this;
@@ -698,7 +703,9 @@ namespace llvm {
}
};
- typedef SingleLinkedListIterator<SubRange> subrange_iterator;
+ using subrange_iterator = SingleLinkedListIterator<SubRange>;
+ using const_subrange_iterator = SingleLinkedListIterator<const SubRange>;
+
subrange_iterator subrange_begin() {
return subrange_iterator(SubRanges);
}
@@ -706,7 +713,6 @@ namespace llvm {
return subrange_iterator(nullptr);
}
- typedef SingleLinkedListIterator<const SubRange> const_subrange_iterator;
const_subrange_iterator subrange_begin() const {
return const_subrange_iterator(SubRanges);
}
@@ -759,12 +765,12 @@ namespace llvm {
/// isSpillable - Can this interval be spilled?
bool isSpillable() const {
- return weight != llvm::huge_valf;
+ return weight != huge_valf;
}
/// markNotSpillable - Mark interval as not spillable
void markNotSpillable() {
- weight = llvm::huge_valf;
+ weight = huge_valf;
}
/// For a given lane mask @p LaneMask, compute indexes at which the
@@ -931,5 +937,7 @@ namespace llvm {
void Distribute(LiveInterval &LI, LiveInterval *LIV[],
MachineRegisterInfo &MRI);
};
-}
-#endif
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_LIVEINTERVAL_H
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 181cb375de86..820e88362483 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -1,4 +1,4 @@
-//===-- LiveIntervalAnalysis.h - Live Interval Analysis ---------*- C++ -*-===//
+//===- LiveIntervalAnalysis.h - Live Interval Analysis ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,6 +20,7 @@
#ifndef LLVM_CODEGEN_LIVEINTERVALANALYSIS_H
#define LLVM_CODEGEN_LIVEINTERVALANALYSIS_H
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
@@ -27,27 +28,29 @@
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/SlotIndexes.h"
-#include "llvm/Support/Allocator.h"
+#include "llvm/MC/LaneBitmask.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetRegisterInfo.h"
-#include <cmath>
+#include <cassert>
+#include <cstdint>
+#include <utility>
namespace llvm {
extern cl::opt<bool> UseSegmentSetForPhysRegs;
- class BitVector;
- class BlockFrequency;
- class LiveRangeCalc;
- class LiveVariables;
- class MachineDominatorTree;
- class MachineLoopInfo;
- class TargetRegisterInfo;
- class MachineRegisterInfo;
- class TargetInstrInfo;
- class TargetRegisterClass;
- class VirtRegMap;
- class MachineBlockFrequencyInfo;
+class BitVector;
+class LiveRangeCalc;
+class MachineBlockFrequencyInfo;
+class MachineDominatorTree;
+class MachineFunction;
+class MachineInstr;
+class MachineRegisterInfo;
+class raw_ostream;
+class TargetInstrInfo;
+class VirtRegMap;
class LiveIntervals : public MachineFunctionPass {
MachineFunction* MF;
@@ -56,8 +59,8 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
const TargetInstrInfo* TII;
AliasAnalysis *AA;
SlotIndexes* Indexes;
- MachineDominatorTree *DomTree;
- LiveRangeCalc *LRCalc;
+ MachineDominatorTree *DomTree = nullptr;
+ LiveRangeCalc *LRCalc = nullptr;
/// Special pool allocator for VNInfo's (LiveInterval val#).
VNInfo::Allocator VNInfoAllocator;
@@ -95,6 +98,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
public:
static char ID;
+
LiveIntervals();
~LiveIntervals() override;
@@ -466,6 +470,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs;
class HMEditor;
};
-} // End llvm namespace
-#endif
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_LIVEINTERVALANALYSIS_H
diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h
index 57e3deb038af..b922e543c856 100644
--- a/include/llvm/CodeGen/LiveIntervalUnion.h
+++ b/include/llvm/CodeGen/LiveIntervalUnion.h
@@ -26,12 +26,14 @@
namespace llvm {
+class raw_ostream;
class TargetRegisterInfo;
#ifndef NDEBUG
// forward declaration
template <unsigned Element> class SparseBitVector;
-typedef SparseBitVector<128> LiveVirtRegBitSet;
+
+using LiveVirtRegBitSet = SparseBitVector<128>;
#endif
/// Union of live intervals that are strong candidates for coalescing into a
@@ -42,19 +44,19 @@ class LiveIntervalUnion {
// A set of live virtual register segments that supports fast insertion,
// intersection, and removal.
// Mapping SlotIndex intervals to virtual register numbers.
- typedef IntervalMap<SlotIndex, LiveInterval*> LiveSegments;
+ using LiveSegments = IntervalMap<SlotIndex, LiveInterval*>;
public:
// SegmentIter can advance to the next segment ordered by starting position
// which may belong to a different live virtual register. We also must be able
// to reach the current segment's containing virtual register.
- typedef LiveSegments::iterator SegmentIter;
+ using SegmentIter = LiveSegments::iterator;
/// Const version of SegmentIter.
- typedef LiveSegments::const_iterator ConstSegmentIter;
+ using ConstSegmentIter = LiveSegments::const_iterator;
// LiveIntervalUnions share an external allocator.
- typedef LiveSegments::Allocator Allocator;
+ using Allocator = LiveSegments::Allocator;
private:
unsigned Tag = 0; // unique tag for current contents.
@@ -76,7 +78,7 @@ public:
SlotIndex startIndex() const { return Segments.start(); }
// Provide public access to the underlying map to allow overlap iteration.
- typedef LiveSegments Map;
+ using Map = LiveSegments;
const Map &getMap() const { return Segments; }
/// getTag - Return an opaque tag representing the current state of the union.
diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h
index 9e04c467fadc..f9c741dd75b2 100644
--- a/include/llvm/CodeGen/LivePhysRegs.h
+++ b/include/llvm/CodeGen/LivePhysRegs.h
@@ -7,23 +7,24 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the LivePhysRegs utility for tracking liveness of
-// physical registers. This can be used for ad-hoc liveness tracking after
-// register allocation. You can start with the live-ins/live-outs at the
-// beginning/end of a block and update the information while walking the
-// instructions inside the block. This implementation tracks the liveness on a
-// sub-register granularity.
-//
-// We assume that the high bits of a physical super-register are not preserved
-// unless the instruction has an implicit-use operand reading the super-
-// register.
-//
-// X86 Example:
-// %YMM0<def> = ...
-// %XMM0<def> = ... (Kills %XMM0, all %XMM0s sub-registers, and %YMM0)
-//
-// %YMM0<def> = ...
-// %XMM0<def> = ..., %YMM0<imp-use> (%YMM0 and all its sub-registers are alive)
+/// \file
+/// This file implements the LivePhysRegs utility for tracking liveness of
+/// physical registers. This can be used for ad-hoc liveness tracking after
+/// register allocation. You can start with the live-ins/live-outs at the
+/// beginning/end of a block and update the information while walking the
+/// instructions inside the block. This implementation tracks the liveness on a
+/// sub-register granularity.
+///
+/// We assume that the high bits of a physical super-register are not preserved
+/// unless the instruction has an implicit-use operand reading the super-
+/// register.
+///
+/// X86 Example:
+/// %YMM0<def> = ...
+/// %XMM0<def> = ... (Kills %XMM0, all %XMM0s sub-registers, and %YMM0)
+///
+/// %YMM0<def> = ...
+/// %XMM0<def> = ..., %YMM0<imp-use> (%YMM0 and all its sub-registers are alive)
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_LIVEPHYSREGS_H
@@ -39,40 +40,42 @@
namespace llvm {
class MachineInstr;
+class MachineOperand;
+class MachineRegisterInfo;
+class raw_ostream;
-/// \brief A set of live physical registers with functions to track liveness
+/// \brief A set of physical registers with utility functions to track liveness
/// when walking backward/forward through a basic block.
class LivePhysRegs {
const TargetRegisterInfo *TRI = nullptr;
SparseSet<unsigned> LiveRegs;
- LivePhysRegs(const LivePhysRegs&) = delete;
- LivePhysRegs &operator=(const LivePhysRegs&) = delete;
-
public:
- /// \brief Constructs a new empty LivePhysRegs set.
+ /// Constructs an unitialized set. init() needs to be called to initialize it.
LivePhysRegs() = default;
- /// \brief Constructs and initialize an empty LivePhysRegs set.
- LivePhysRegs(const TargetRegisterInfo *TRI) : TRI(TRI) {
- assert(TRI && "Invalid TargetRegisterInfo pointer.");
- LiveRegs.setUniverse(TRI->getNumRegs());
+ /// Constructs and initializes an empty set.
+ LivePhysRegs(const TargetRegisterInfo &TRI) : TRI(&TRI) {
+ LiveRegs.setUniverse(TRI.getNumRegs());
}
- /// \brief Clear and initialize the LivePhysRegs set.
+ LivePhysRegs(const LivePhysRegs&) = delete;
+ LivePhysRegs &operator=(const LivePhysRegs&) = delete;
+
+ /// (re-)initializes and clears the set.
void init(const TargetRegisterInfo &TRI) {
this->TRI = &TRI;
LiveRegs.clear();
LiveRegs.setUniverse(TRI.getNumRegs());
}
- /// \brief Clears the LivePhysRegs set.
+ /// Clears the set.
void clear() { LiveRegs.clear(); }
- /// \brief Returns true if the set is empty.
+ /// Returns true if the set is empty.
bool empty() const { return LiveRegs.empty(); }
- /// \brief Adds a physical register and all its sub-registers to the set.
+ /// Adds a physical register and all its sub-registers to the set.
void addReg(unsigned Reg) {
assert(TRI && "LivePhysRegs is not initialized.");
assert(Reg <= TRI->getNumRegs() && "Expected a physical register.");
@@ -90,12 +93,13 @@ public:
LiveRegs.erase(*R);
}
- /// \brief Removes physical registers clobbered by the regmask operand @p MO.
+ /// Removes physical registers clobbered by the regmask operand \p MO.
void removeRegsInMask(const MachineOperand &MO,
- SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers);
+ SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> *Clobbers =
+ nullptr);
- /// \brief Returns true if register @p Reg is contained in the set. This also
- /// works if only the super register of @p Reg has been defined, because
+ /// \brief Returns true if register \p Reg is contained in the set. This also
+ /// works if only the super register of \p Reg has been defined, because
/// addReg() always adds all sub-registers to the set as well.
/// Note: Returns false if just some sub registers are live, use available()
/// when searching a free register.
@@ -104,48 +108,48 @@ public:
/// Returns true if register \p Reg and no aliasing register is in the set.
bool available(const MachineRegisterInfo &MRI, unsigned Reg) const;
- /// \brief Simulates liveness when stepping backwards over an
- /// instruction(bundle): Remove Defs, add uses. This is the recommended way of
- /// calculating liveness.
+ /// Simulates liveness when stepping backwards over an instruction(bundle).
+ /// Remove Defs, add uses. This is the recommended way of calculating
+ /// liveness.
void stepBackward(const MachineInstr &MI);
- /// \brief Simulates liveness when stepping forward over an
- /// instruction(bundle): Remove killed-uses, add defs. This is the not
- /// recommended way, because it depends on accurate kill flags. If possible
- /// use stepBackward() instead of this function.
- /// The clobbers set will be the list of registers either defined or clobbered
- /// by a regmask. The operand will identify whether this is a regmask or
- /// register operand.
+ /// Simulates liveness when stepping forward over an instruction(bundle).
+ /// Remove killed-uses, add defs. This is the not recommended way, because it
+ /// depends on accurate kill flags. If possible use stepBackward() instead of
+ /// this function. The clobbers set will be the list of registers either
+ /// defined or clobbered by a regmask. The operand will identify whether this
+ /// is a regmask or register operand.
void stepForward(const MachineInstr &MI,
SmallVectorImpl<std::pair<unsigned, const MachineOperand*>> &Clobbers);
- /// Adds all live-in registers of basic block @p MBB.
+ /// Adds all live-in registers of basic block \p MBB.
/// Live in registers are the registers in the blocks live-in list and the
/// pristine registers.
void addLiveIns(const MachineBasicBlock &MBB);
- /// Adds all live-out registers of basic block @p MBB.
+ /// Adds all live-out registers of basic block \p MBB.
/// Live out registers are the union of the live-in registers of the successor
/// blocks and pristine registers. Live out registers of the end block are the
/// callee saved registers.
void addLiveOuts(const MachineBasicBlock &MBB);
- /// Like addLiveOuts() but does not add pristine registers/callee saved
+ /// Adds all live-out registers of basic block \p MBB but skips pristine
/// registers.
void addLiveOutsNoPristines(const MachineBasicBlock &MBB);
- typedef SparseSet<unsigned>::const_iterator const_iterator;
+ using const_iterator = SparseSet<unsigned>::const_iterator;
+
const_iterator begin() const { return LiveRegs.begin(); }
const_iterator end() const { return LiveRegs.end(); }
- /// \brief Prints the currently live registers to @p OS.
+ /// Prints the currently live registers to \p OS.
void print(raw_ostream &OS) const;
- /// \brief Dumps the currently live registers to the debug output.
+ /// Dumps the currently live registers to the debug output.
void dump() const;
private:
- /// Adds live-in registers from basic block @p MBB, taking associated
+ /// \brief Adds live-in registers from basic block \p MBB, taking associated
/// lane masks into consideration.
void addBlockLiveIns(const MachineBasicBlock &MBB);
};
@@ -155,11 +159,11 @@ inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) {
return OS;
}
-/// Compute the live-in list for \p MBB assuming all of its successors live-in
-/// lists are up-to-date. Uses the given LivePhysReg instance \p LiveRegs; This
-/// is just here to avoid repeated heap allocations when calling this multiple
-/// times in a pass.
-void computeLiveIns(LivePhysRegs &LiveRegs, const TargetRegisterInfo &TRI,
+/// \brief Computes the live-in list for \p MBB assuming all of its successors
+/// live-in lists are up-to-date. Uses the given LivePhysReg instance \p
+/// LiveRegs; This is just here to avoid repeated heap allocations when calling
+/// this multiple times in a pass.
+void computeLiveIns(LivePhysRegs &LiveRegs, const MachineRegisterInfo &MRI,
MachineBasicBlock &MBB);
} // end namespace llvm
diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h
index 4250777682ba..362d9854a271 100644
--- a/include/llvm/CodeGen/LiveRangeEdit.h
+++ b/include/llvm/CodeGen/LiveRangeEdit.h
@@ -1,4 +1,4 @@
-//===---- LiveRangeEdit.h - Basic tools for split and spill -----*- C++ -*-===//
+//===- LiveRangeEdit.h - Basic tools for split and spill --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -19,19 +19,28 @@
#define LLVM_CODEGEN_LIVERANGEEDIT_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/None.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/LiveInterval.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetMachine.h"
+#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/Target/TargetSubtargetInfo.h"
+#include <cassert>
namespace llvm {
class LiveIntervals;
class MachineBlockFrequencyInfo;
+class MachineInstr;
class MachineLoopInfo;
+class MachineOperand;
+class TargetInstrInfo;
+class TargetRegisterInfo;
class VirtRegMap;
class LiveRangeEdit : private MachineRegisterInfo::Delegate {
@@ -39,7 +48,10 @@ public:
/// Callback methods for LiveRangeEdit owners.
class Delegate {
virtual void anchor();
+
public:
+ virtual ~Delegate() = default;
+
/// Called immediately before erasing a dead machine instruction.
virtual void LRE_WillEraseInstruction(MachineInstr *MI) {}
@@ -53,8 +65,6 @@ public:
/// Called after cloning a virtual register.
/// This is used for new registers representing connected components of Old.
virtual void LRE_DidCloneVirtReg(unsigned New, unsigned Old) {}
-
- virtual ~Delegate() {}
};
private:
@@ -70,7 +80,7 @@ private:
const unsigned FirstNew;
/// ScannedRemattable - true when remattable values have been identified.
- bool ScannedRemattable;
+ bool ScannedRemattable = false;
/// DeadRemats - The saved instructions which have already been dead after
/// rematerialization but not deleted yet -- to be done in postOptimization.
@@ -78,11 +88,11 @@ private:
/// Remattable - Values defined by remattable instructions as identified by
/// tii.isTriviallyReMaterializable().
- SmallPtrSet<const VNInfo*,4> Remattable;
+ SmallPtrSet<const VNInfo *, 4> Remattable;
/// Rematted - Values that were actually rematted, and so need to have their
/// live range trimmed or entirely removed.
- SmallPtrSet<const VNInfo*,4> Rematted;
+ SmallPtrSet<const VNInfo *, 4> Rematted;
/// scanRemattable - Identify the Parent values that may rematerialize.
void scanRemattable(AliasAnalysis *aa);
@@ -94,11 +104,11 @@ private:
/// foldAsLoad - If LI has a single use and a single def that can be folded as
/// a load, eliminate the register by folding the def into the use.
- bool foldAsLoad(LiveInterval *LI, SmallVectorImpl<MachineInstr*> &Dead);
+ bool foldAsLoad(LiveInterval *LI, SmallVectorImpl<MachineInstr *> &Dead);
+
+ using ToShrinkSet = SetVector<LiveInterval *, SmallVector<LiveInterval *, 8>,
+ SmallPtrSet<LiveInterval *, 8>>;
- typedef SetVector<LiveInterval*,
- SmallVector<LiveInterval*, 8>,
- SmallPtrSet<LiveInterval*, 8> > ToShrinkSet;
/// Helper for eliminateDeadDefs.
void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink,
AliasAnalysis *AA);
@@ -129,26 +139,26 @@ public:
SmallPtrSet<MachineInstr *, 32> *deadRemats = nullptr)
: Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis),
VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()), TheDelegate(delegate),
- FirstNew(newRegs.size()), ScannedRemattable(false),
- DeadRemats(deadRemats) {
+ FirstNew(newRegs.size()), DeadRemats(deadRemats) {
MRI.setDelegate(this);
}
~LiveRangeEdit() override { MRI.resetDelegate(this); }
LiveInterval &getParent() const {
- assert(Parent && "No parent LiveInterval");
- return *Parent;
+ assert(Parent && "No parent LiveInterval");
+ return *Parent;
}
+
unsigned getReg() const { return getParent().reg; }
/// Iterator for accessing the new registers added by this edit.
- typedef SmallVectorImpl<unsigned>::const_iterator iterator;
- iterator begin() const { return NewRegs.begin()+FirstNew; }
+ using iterator = SmallVectorImpl<unsigned>::const_iterator;
+ iterator begin() const { return NewRegs.begin() + FirstNew; }
iterator end() const { return NewRegs.end(); }
- unsigned size() const { return NewRegs.size()-FirstNew; }
+ unsigned size() const { return NewRegs.size() - FirstNew; }
bool empty() const { return size() == 0; }
- unsigned get(unsigned idx) const { return NewRegs[idx+FirstNew]; }
+ unsigned get(unsigned idx) const { return NewRegs[idx + FirstNew]; }
/// pop_back - It allows LiveRangeEdit users to drop new registers.
/// The context is when an original def instruction of a register is
@@ -176,26 +186,25 @@ public:
return createEmptyIntervalFrom(getReg());
}
- unsigned create() {
- return createFrom(getReg());
- }
+ unsigned create() { return createFrom(getReg()); }
/// anyRematerializable - Return true if any parent values may be
/// rematerializable.
/// This function must be called before any rematerialization is attempted.
- bool anyRematerializable(AliasAnalysis*);
+ bool anyRematerializable(AliasAnalysis *);
/// checkRematerializable - Manually add VNI to the list of rematerializable
/// values if DefMI may be rematerializable.
bool checkRematerializable(VNInfo *VNI, const MachineInstr *DefMI,
- AliasAnalysis*);
+ AliasAnalysis *);
/// Remat - Information needed to rematerialize at a specific location.
struct Remat {
- VNInfo *ParentVNI; // parent_'s value at the remat location.
- MachineInstr *OrigMI; // Instruction defining OrigVNI. It contains the
- // real expr for remat.
- explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI), OrigMI(nullptr) {}
+ VNInfo *ParentVNI; // parent_'s value at the remat location.
+ MachineInstr *OrigMI = nullptr; // Instruction defining OrigVNI. It contains
+ // the real expr for remat.
+
+ explicit Remat(VNInfo *ParentVNI) : ParentVNI(ParentVNI) {}
};
/// canRematerializeAt - Determine if ParentVNI can be rematerialized at
@@ -209,10 +218,8 @@ public:
/// liveness is not updated.
/// Return the SlotIndex of the new instruction.
SlotIndex rematerializeAt(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg,
- const Remat &RM,
- const TargetRegisterInfo&,
+ MachineBasicBlock::iterator MI, unsigned DestReg,
+ const Remat &RM, const TargetRegisterInfo &,
bool Late = false);
/// markRematerialized - explicitly mark a value as rematerialized after doing
@@ -248,11 +255,10 @@ public:
/// calculateRegClassAndHint - Recompute register class and hint for each new
/// register.
- void calculateRegClassAndHint(MachineFunction&,
- const MachineLoopInfo&,
- const MachineBlockFrequencyInfo&);
+ void calculateRegClassAndHint(MachineFunction &, const MachineLoopInfo &,
+ const MachineBlockFrequencyInfo &);
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_LIVERANGEEDIT_H
diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h
index 3ffbe3d775b4..c90ae7b184f4 100644
--- a/include/llvm/CodeGen/LiveStackAnalysis.h
+++ b/include/llvm/CodeGen/LiveStackAnalysis.h
@@ -1,4 +1,4 @@
-//===-- LiveStackAnalysis.h - Live Stack Slot Analysis ----------*- C++ -*-===//
+//===- LiveStackAnalysis.h - Live Stack Slot Analysis -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,13 +18,16 @@
#include "llvm/CodeGen/LiveInterval.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Pass.h"
+#include <cassert>
#include <map>
#include <unordered_map>
namespace llvm {
+class TargetRegisterClass;
+class TargetRegisterInfo;
+
class LiveStacks : public MachineFunctionPass {
const TargetRegisterInfo *TRI;
@@ -33,8 +36,7 @@ class LiveStacks : public MachineFunctionPass {
VNInfo::Allocator VNInfoAllocator;
/// S2IMap - Stack slot indices to live interval mapping.
- ///
- typedef std::unordered_map<int, LiveInterval> SS2IntervalMap;
+ using SS2IntervalMap = std::unordered_map<int, LiveInterval>;
SS2IntervalMap S2IMap;
/// S2RCMap - Stack slot indices to register class mapping.
@@ -42,12 +44,14 @@ class LiveStacks : public MachineFunctionPass {
public:
static char ID; // Pass identification, replacement for typeid
+
LiveStacks() : MachineFunctionPass(ID) {
initializeLiveStacksPass(*PassRegistry::getPassRegistry());
}
- typedef SS2IntervalMap::iterator iterator;
- typedef SS2IntervalMap::const_iterator const_iterator;
+ using iterator = SS2IntervalMap::iterator;
+ using const_iterator = SS2IntervalMap::const_iterator;
+
const_iterator begin() const { return S2IMap.begin(); }
const_iterator end() const { return S2IMap.end(); }
iterator begin() { return S2IMap.begin(); }
@@ -93,6 +97,7 @@ public:
/// print - Implement the dump method.
void print(raw_ostream &O, const Module * = nullptr) const override;
};
-}
-#endif /* LLVM_CODEGEN_LIVESTACK_ANALYSIS_H */
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_LIVESTACK_ANALYSIS_H
diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h
index 18d40564856d..8da48c379d00 100644
--- a/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/include/llvm/CodeGen/MachineBasicBlock.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/MachineBasicBlock.h ------------------------*- C++ -*-===//
+//===- llvm/CodeGen/MachineBasicBlock.h -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -15,41 +15,50 @@
#define LLVM_CODEGEN_MACHINEBASICBLOCK_H
#include "llvm/ADT/GraphTraits.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/simple_ilist.h"
#include "llvm/CodeGen/MachineInstrBundleIterator.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/MC/LaneBitmask.h"
#include "llvm/MC/MCRegisterInfo.h"
-#include "llvm/Support/DataTypes.h"
+#include <cassert>
+#include <cstdint>
#include <functional>
+#include <iterator>
+#include <string>
+#include <vector>
namespace llvm {
-class Pass;
class BasicBlock;
class MachineFunction;
class MCSymbol;
-class MIPrinter;
+class ModuleSlotTracker;
+class Pass;
class SlotIndexes;
class StringRef;
class raw_ostream;
-class MachineBranchProbabilityInfo;
+class TargetRegisterClass;
+class TargetRegisterInfo;
template <> struct ilist_traits<MachineInstr> {
private:
friend class MachineBasicBlock; // Set by the owning MachineBasicBlock.
+
MachineBasicBlock *Parent;
- typedef simple_ilist<MachineInstr, ilist_sentinel_tracking<true>>::iterator
- instr_iterator;
+ using instr_iterator =
+ simple_ilist<MachineInstr, ilist_sentinel_tracking<true>>::iterator;
public:
void addNodeToList(MachineInstr *N);
void removeNodeFromList(MachineInstr *N);
void transferNodesFromList(ilist_traits &OldList, instr_iterator First,
instr_iterator Last);
-
void deleteNode(MachineInstr *MI);
};
@@ -69,7 +78,8 @@ public:
};
private:
- typedef ilist<MachineInstr, ilist_sentinel_tracking<true>> Instructions;
+ using Instructions = ilist<MachineInstr, ilist_sentinel_tracking<true>>;
+
Instructions Insts;
const BasicBlock *BB;
int Number;
@@ -83,12 +93,12 @@ private:
/// same order as Successors, or it is empty if we don't use it (disable
/// optimization).
std::vector<BranchProbability> Probs;
- typedef std::vector<BranchProbability>::iterator probability_iterator;
- typedef std::vector<BranchProbability>::const_iterator
- const_probability_iterator;
+ using probability_iterator = std::vector<BranchProbability>::iterator;
+ using const_probability_iterator =
+ std::vector<BranchProbability>::const_iterator;
/// Keep track of the physical registers that are livein of the basicblock.
- typedef std::vector<RegisterMaskPair> LiveInVector;
+ using LiveInVector = std::vector<RegisterMaskPair>;
LiveInVector LiveIns;
/// Alignment of the basic block. Zero if the basic block does not need to be
@@ -113,7 +123,7 @@ private:
mutable MCSymbol *CachedMCSymbol = nullptr;
// Intrusive list support
- MachineBasicBlock() {}
+ MachineBasicBlock() = default;
explicit MachineBasicBlock(MachineFunction &MF, const BasicBlock *BB);
@@ -145,16 +155,16 @@ public:
const MachineFunction *getParent() const { return xParent; }
MachineFunction *getParent() { return xParent; }
- typedef Instructions::iterator instr_iterator;
- typedef Instructions::const_iterator const_instr_iterator;
- typedef Instructions::reverse_iterator reverse_instr_iterator;
- typedef Instructions::const_reverse_iterator const_reverse_instr_iterator;
+ using instr_iterator = Instructions::iterator;
+ using const_instr_iterator = Instructions::const_iterator;
+ using reverse_instr_iterator = Instructions::reverse_iterator;
+ using const_reverse_instr_iterator = Instructions::const_reverse_iterator;
- typedef MachineInstrBundleIterator<MachineInstr> iterator;
- typedef MachineInstrBundleIterator<const MachineInstr> const_iterator;
- typedef MachineInstrBundleIterator<MachineInstr, true> reverse_iterator;
- typedef MachineInstrBundleIterator<const MachineInstr, true>
- const_reverse_iterator;
+ using iterator = MachineInstrBundleIterator<MachineInstr>;
+ using const_iterator = MachineInstrBundleIterator<const MachineInstr>;
+ using reverse_iterator = MachineInstrBundleIterator<MachineInstr, true>;
+ using const_reverse_iterator =
+ MachineInstrBundleIterator<const MachineInstr, true>;
unsigned size() const { return (unsigned)Insts.size(); }
bool empty() const { return Insts.empty(); }
@@ -178,8 +188,8 @@ public:
reverse_instr_iterator instr_rend () { return Insts.rend(); }
const_reverse_instr_iterator instr_rend () const { return Insts.rend(); }
- typedef iterator_range<instr_iterator> instr_range;
- typedef iterator_range<const_instr_iterator> const_instr_range;
+ using instr_range = iterator_range<instr_iterator>;
+ using const_instr_range = iterator_range<const_instr_iterator>;
instr_range instrs() { return instr_range(instr_begin(), instr_end()); }
const_instr_range instrs() const {
return const_instr_range(instr_begin(), instr_end());
@@ -213,18 +223,18 @@ public:
}
// Machine-CFG iterators
- typedef std::vector<MachineBasicBlock *>::iterator pred_iterator;
- typedef std::vector<MachineBasicBlock *>::const_iterator const_pred_iterator;
- typedef std::vector<MachineBasicBlock *>::iterator succ_iterator;
- typedef std::vector<MachineBasicBlock *>::const_iterator const_succ_iterator;
- typedef std::vector<MachineBasicBlock *>::reverse_iterator
- pred_reverse_iterator;
- typedef std::vector<MachineBasicBlock *>::const_reverse_iterator
- const_pred_reverse_iterator;
- typedef std::vector<MachineBasicBlock *>::reverse_iterator
- succ_reverse_iterator;
- typedef std::vector<MachineBasicBlock *>::const_reverse_iterator
- const_succ_reverse_iterator;
+ using pred_iterator = std::vector<MachineBasicBlock *>::iterator;
+ using const_pred_iterator = std::vector<MachineBasicBlock *>::const_iterator;
+ using succ_iterator = std::vector<MachineBasicBlock *>::iterator;
+ using const_succ_iterator = std::vector<MachineBasicBlock *>::const_iterator;
+ using pred_reverse_iterator =
+ std::vector<MachineBasicBlock *>::reverse_iterator;
+ using const_pred_reverse_iterator =
+ std::vector<MachineBasicBlock *>::const_reverse_iterator;
+ using succ_reverse_iterator =
+ std::vector<MachineBasicBlock *>::reverse_iterator;
+ using const_succ_reverse_iterator =
+ std::vector<MachineBasicBlock *>::const_reverse_iterator;
pred_iterator pred_begin() { return Predecessors.begin(); }
const_pred_iterator pred_begin() const { return Predecessors.begin(); }
pred_iterator pred_end() { return Predecessors.end(); }
@@ -307,7 +317,7 @@ public:
// Iteration support for live in sets. These sets are kept in sorted
// order by their register number.
- typedef LiveInVector::const_iterator livein_iterator;
+ using livein_iterator = LiveInVector::const_iterator;
#ifndef NDEBUG
/// Unlike livein_begin, this method does not check that the liveness
/// information is accurate. Still for debug purposes it may be useful
@@ -455,7 +465,6 @@ public:
/// other block.
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const;
-
/// Return the fallthrough block if the block can implicitly
/// transfer control to the block after it by falling off the end of
/// it. This should return null if it can reach the block after
@@ -695,7 +704,7 @@ public:
LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI,
unsigned Reg,
const_iterator Before,
- unsigned Neighborhood=10) const;
+ unsigned Neighborhood = 10) const;
// Debugging methods.
void dump() const;
@@ -714,7 +723,6 @@ public:
/// Return the MCSymbol for this basic block.
MCSymbol *getSymbol() const;
-
private:
/// Return probability iterator corresponding to the I successor iterator.
probability_iterator getProbabilityIterator(succ_iterator I);
@@ -764,8 +772,8 @@ struct MBB2NumberFunctor :
//
template <> struct GraphTraits<MachineBasicBlock *> {
- typedef MachineBasicBlock *NodeRef;
- typedef MachineBasicBlock::succ_iterator ChildIteratorType;
+ using NodeRef = MachineBasicBlock *;
+ using ChildIteratorType = MachineBasicBlock::succ_iterator;
static NodeRef getEntryNode(MachineBasicBlock *BB) { return BB; }
static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
@@ -773,8 +781,8 @@ template <> struct GraphTraits<MachineBasicBlock *> {
};
template <> struct GraphTraits<const MachineBasicBlock *> {
- typedef const MachineBasicBlock *NodeRef;
- typedef MachineBasicBlock::const_succ_iterator ChildIteratorType;
+ using NodeRef = const MachineBasicBlock *;
+ using ChildIteratorType = MachineBasicBlock::const_succ_iterator;
static NodeRef getEntryNode(const MachineBasicBlock *BB) { return BB; }
static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); }
@@ -787,28 +795,30 @@ template <> struct GraphTraits<const MachineBasicBlock *> {
// to be when traversing the predecessor edges of a MBB
// instead of the successor edges.
//
-template <> struct GraphTraits<Inverse<MachineBasicBlock*> > {
- typedef MachineBasicBlock *NodeRef;
- typedef MachineBasicBlock::pred_iterator ChildIteratorType;
+template <> struct GraphTraits<Inverse<MachineBasicBlock*>> {
+ using NodeRef = MachineBasicBlock *;
+ using ChildIteratorType = MachineBasicBlock::pred_iterator;
+
static NodeRef getEntryNode(Inverse<MachineBasicBlock *> G) {
return G.Graph;
}
+
static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
-template <> struct GraphTraits<Inverse<const MachineBasicBlock*> > {
- typedef const MachineBasicBlock *NodeRef;
- typedef MachineBasicBlock::const_pred_iterator ChildIteratorType;
+template <> struct GraphTraits<Inverse<const MachineBasicBlock*>> {
+ using NodeRef = const MachineBasicBlock *;
+ using ChildIteratorType = MachineBasicBlock::const_pred_iterator;
+
static NodeRef getEntryNode(Inverse<const MachineBasicBlock *> G) {
return G.Graph;
}
+
static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); }
static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
-
-
/// MachineInstrSpan provides an interface to get an iteration range
/// containing the instruction it was initialized with, along with all
/// those instructions inserted prior to or following that instruction
@@ -816,6 +826,7 @@ template <> struct GraphTraits<Inverse<const MachineBasicBlock*> > {
class MachineInstrSpan {
MachineBasicBlock &MBB;
MachineBasicBlock::iterator I, B, E;
+
public:
MachineInstrSpan(MachineBasicBlock::iterator I)
: MBB(*I->getParent()),
@@ -854,6 +865,6 @@ inline IterT skipDebugInstructionsBackward(IterT It, IterT Begin) {
return It;
}
-} // End llvm namespace
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEBASICBLOCK_H
diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
index cd1c204981ed..cba79c818a76 100644
--- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
+++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h
@@ -1,4 +1,4 @@
-//===- MachineBlockFrequencyInfo.h - MBB Frequency Analysis -*- C++ -*-----===//
+//===- MachineBlockFrequencyInfo.h - MBB Frequency Analysis -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -17,26 +17,28 @@
#include "llvm/ADT/Optional.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/BlockFrequency.h"
-#include <climits>
+#include <cstdint>
+#include <memory>
namespace llvm {
+template <class BlockT> class BlockFrequencyInfoImpl;
class MachineBasicBlock;
class MachineBranchProbabilityInfo;
+class MachineFunction;
class MachineLoopInfo;
-template <class BlockT> class BlockFrequencyInfoImpl;
+class raw_ostream;
/// MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation
/// to estimate machine basic block frequencies.
class MachineBlockFrequencyInfo : public MachineFunctionPass {
- typedef BlockFrequencyInfoImpl<MachineBasicBlock> ImplType;
+ using ImplType = BlockFrequencyInfoImpl<MachineBasicBlock>;
std::unique_ptr<ImplType> MBFI;
public:
static char ID;
MachineBlockFrequencyInfo();
-
~MachineBlockFrequencyInfo() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
@@ -74,9 +76,8 @@ public:
const MachineBasicBlock *MBB) const;
uint64_t getEntryFreq() const;
-
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h
index 4131194a0c0f..370ffbe4862e 100644
--- a/include/llvm/CodeGen/MachineDominanceFrontier.h
+++ b/include/llvm/CodeGen/MachineDominanceFrontier.h
@@ -11,23 +11,28 @@
#define LLVM_CODEGEN_MACHINEDOMINANCEFRONTIER_H
#include "llvm/Analysis/DominanceFrontier.h"
+#include "llvm/Analysis/DominanceFrontierImpl.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
-
+#include "llvm/Support/GenericDomTree.h"
+#include <vector>
namespace llvm {
class MachineDominanceFrontier : public MachineFunctionPass {
ForwardDominanceFrontierBase<MachineBasicBlock> Base;
+
public:
- typedef DominatorTreeBase<MachineBasicBlock> DomTreeT;
- typedef DomTreeNodeBase<MachineBasicBlock> DomTreeNodeT;
- typedef DominanceFrontierBase<MachineBasicBlock>::DomSetType DomSetType;
- typedef DominanceFrontierBase<MachineBasicBlock>::iterator iterator;
- typedef DominanceFrontierBase<MachineBasicBlock>::const_iterator const_iterator;
+ using DomTreeT = DominatorTreeBase<MachineBasicBlock>;
+ using DomTreeNodeT = DomTreeNodeBase<MachineBasicBlock>;
+ using DomSetType = DominanceFrontierBase<MachineBasicBlock>::DomSetType;
+ using iterator = DominanceFrontierBase<MachineBasicBlock>::iterator;
+ using const_iterator =
+ DominanceFrontierBase<MachineBasicBlock>::const_iterator;
- void operator=(const MachineDominanceFrontier &) = delete;
MachineDominanceFrontier(const MachineDominanceFrontier &) = delete;
+ MachineDominanceFrontier &
+ operator=(const MachineDominanceFrontier &) = delete;
static char ID;
@@ -104,6 +109,6 @@ public:
void getAnalysisUsage(AnalysisUsage &AU) const override;
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEDOMINANCEFRONTIER_H
diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h
index 30b6cfdd1c36..74a7c3ea04ae 100644
--- a/include/llvm/CodeGen/MachineDominators.h
+++ b/include/llvm/CodeGen/MachineDominators.h
@@ -1,4 +1,4 @@
-//=- llvm/CodeGen/MachineDominators.h - Machine Dom Calculation --*- C++ -*-==//
+//==- llvm/CodeGen/MachineDominators.h - Machine Dom Calculation -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
@@ -16,12 +16,15 @@
#define LLVM_CODEGEN_MACHINEDOMINATORS_H
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
+#include <cassert>
#include <memory>
+#include <vector>
namespace llvm {
@@ -33,7 +36,7 @@ inline void DominatorTreeBase<MachineBasicBlock>::addRoot(MachineBasicBlock* MBB
extern template class DomTreeNodeBase<MachineBasicBlock>;
extern template class DominatorTreeBase<MachineBasicBlock>;
-typedef DomTreeNodeBase<MachineBasicBlock> MachineDomTreeNode;
+using MachineDomTreeNode = DomTreeNodeBase<MachineBasicBlock>;
//===-------------------------------------
/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to
@@ -52,6 +55,7 @@ class MachineDominatorTree : public MachineFunctionPass {
/// The splitting of a critical edge is local and thus, it is possible
/// to apply several of those changes at the same time.
mutable SmallVector<CriticalEdge, 32> CriticalEdgesToSplit;
+
/// \brief Remember all the basic blocks that are inserted during
/// edge splitting.
/// Invariant: NewBBs == all the basic blocks contained in the NewBB
@@ -259,8 +263,8 @@ public:
template <class Node, class ChildIterator>
struct MachineDomTreeGraphTraitsBase {
- typedef Node *NodeRef;
- typedef ChildIterator ChildIteratorType;
+ using NodeRef = Node *;
+ using ChildIteratorType = ChildIterator;
static NodeRef getEntryNode(NodeRef N) { return N; }
static ChildIteratorType child_begin(NodeRef N) { return N->begin(); }
@@ -287,6 +291,6 @@ template <> struct GraphTraits<MachineDominatorTree*>
}
};
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_CODEGEN_MACHINEDOMINATORS_H
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index e7e728c1be28..8d040beff7a6 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -826,26 +826,35 @@ public:
getOperand(0).getSubReg() == getOperand(1).getSubReg();
}
- /// Return true if this is a transient instruction that is
- /// either very likely to be eliminated during register allocation (such as
- /// copy-like instructions), or if this instruction doesn't have an
- /// execution-time cost.
+ /// Return true if this instruction doesn't produce any output in the form of
+ /// executable instructions.
+ bool isMetaInstruction() const {
+ switch (getOpcode()) {
+ default:
+ return false;
+ case TargetOpcode::IMPLICIT_DEF:
+ case TargetOpcode::KILL:
+ case TargetOpcode::CFI_INSTRUCTION:
+ case TargetOpcode::EH_LABEL:
+ case TargetOpcode::GC_LABEL:
+ case TargetOpcode::DBG_VALUE:
+ return true;
+ }
+ }
+
+ /// Return true if this is a transient instruction that is either very likely
+ /// to be eliminated during register allocation (such as copy-like
+ /// instructions), or if this instruction doesn't have an execution-time cost.
bool isTransient() const {
- switch(getOpcode()) {
- default: return false;
+ switch (getOpcode()) {
+ default:
+ return isMetaInstruction();
// Copy-like instructions are usually eliminated during register allocation.
case TargetOpcode::PHI:
case TargetOpcode::COPY:
case TargetOpcode::INSERT_SUBREG:
case TargetOpcode::SUBREG_TO_REG:
case TargetOpcode::REG_SEQUENCE:
- // Pseudo-instructions that don't produce any real output.
- case TargetOpcode::IMPLICIT_DEF:
- case TargetOpcode::KILL:
- case TargetOpcode::CFI_INSTRUCTION:
- case TargetOpcode::EH_LABEL:
- case TargetOpcode::GC_LABEL:
- case TargetOpcode::DBG_VALUE:
return true;
}
}
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 6e5c6473ff4a..1026654da3d7 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -642,6 +642,11 @@ public:
///
void setRegBank(unsigned Reg, const RegisterBank &RegBank);
+ void setRegClassOrRegBank(unsigned Reg,
+ const RegClassOrRegBank &RCOrRB){
+ VRegInfo[Reg].first = RCOrRB;
+ }
+
/// constrainRegClass - Constrain the register class of the specified virtual
/// register to be a common subclass of RC and the current register class,
/// but only if the new class has at least MinNumRegs registers. Return the
diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h
index e92bb7f74967..d991e4c216d9 100644
--- a/include/llvm/CodeGen/MachineValueType.h
+++ b/include/llvm/CodeGen/MachineValueType.h
@@ -26,7 +26,7 @@ namespace llvm {
/// Machine Value Type. Every type that is supported natively by some
/// processor targeted by LLVM occurs here. This means that any legal value
/// type can be represented by an MVT.
-class MVT {
+ class MVT {
public:
enum SimpleValueType : uint8_t {
// Simple value types that aren't explicitly part of this enumeration
diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h
index 99afd8c5c9ab..97aa2aace822 100644
--- a/include/llvm/CodeGen/ScheduleDAG.h
+++ b/include/llvm/CodeGen/ScheduleDAG.h
@@ -52,14 +52,14 @@ class TargetRegisterInfo;
/// These are the different kinds of scheduling dependencies.
enum Kind {
Data, ///< Regular data dependence (aka true-dependence).
- Anti, ///< A register anti-dependedence (aka WAR).
+ Anti, ///< A register anti-dependence (aka WAR).
Output, ///< A register output-dependence (aka WAW).
Order ///< Any other ordering dependency.
};
// Strong dependencies must be respected by the scheduler. Artificial
// dependencies may be removed only if they are redundant with another
- // strong depedence.
+ // strong dependence.
//
// Weak dependencies may be violated by the scheduling strategy, but only if
// the strategy can prove it is correct to do so.
@@ -342,7 +342,7 @@ class TargetRegisterInfo;
/// BoundaryNodes can have DAG edges, including Data edges, but they do not
/// correspond to schedulable entities (e.g. instructions) and do not have a
/// valid ID. Consequently, always check for boundary nodes before accessing
- /// an assoicative data structure keyed on node ID.
+ /// an associative data structure keyed on node ID.
bool isBoundaryNode() const { return NodeNum == BoundaryID; }
/// Assigns the representative SDNode for this SUnit. This may be used
diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h
index 21e1740aa6b8..f5f5bfd45e79 100644
--- a/include/llvm/CodeGen/ScheduleDAGInstrs.h
+++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SparseMultiSet.h"
#include "llvm/ADT/SparseSet.h"
+#include "llvm/CodeGen/LivePhysRegs.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/Compiler.h"
@@ -224,7 +225,7 @@ namespace llvm {
MachineInstr *FirstDbgValue;
/// Set of live physical registers for updating kill flags.
- BitVector LiveRegs;
+ LivePhysRegs LiveRegs;
public:
explicit ScheduleDAGInstrs(MachineFunction &mf,
@@ -311,7 +312,7 @@ namespace llvm {
std::string getDAGName() const override;
/// Fixes register kill flags that scheduling has made invalid.
- void fixupKills(MachineBasicBlock *MBB);
+ void fixupKills(MachineBasicBlock &MBB);
protected:
void initSUnits();
diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h
index d761661f763e..493122b15704 100644
--- a/include/llvm/CodeGen/SelectionDAG.h
+++ b/include/llvm/CodeGen/SelectionDAG.h
@@ -1070,6 +1070,11 @@ public:
SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs,
ArrayRef<SDValue> Ops);
+ /// Mutate the specified strict FP node to its non-strict equivalent,
+ /// unlinking the node from its chain and dropping the metadata arguments.
+ /// The node must be a strict FP node.
+ SDNode *mutateStrictFPToFP(SDNode *Node);
+
/// These are used for target selectors to create a new node
/// with specified return type(s), MachineInstr opcode, and operands.
///
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 35ddcf80c91f..973c5aac5281 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -612,6 +612,32 @@ public:
SDNodeBits.IsMemIntrinsic;
}
+ /// Test if this node is a strict floating point pseudo-op.
+ bool isStrictFPOpcode() {
+ switch (NodeType) {
+ default:
+ return false;
+ case ISD::STRICT_FADD:
+ case ISD::STRICT_FSUB:
+ case ISD::STRICT_FMUL:
+ case ISD::STRICT_FDIV:
+ case ISD::STRICT_FREM:
+ case ISD::STRICT_FSQRT:
+ case ISD::STRICT_FPOW:
+ case ISD::STRICT_FPOWI:
+ case ISD::STRICT_FSIN:
+ case ISD::STRICT_FCOS:
+ case ISD::STRICT_FEXP:
+ case ISD::STRICT_FEXP2:
+ case ISD::STRICT_FLOG:
+ case ISD::STRICT_FLOG10:
+ case ISD::STRICT_FLOG2:
+ case ISD::STRICT_FRINT:
+ case ISD::STRICT_FNEARBYINT:
+ return true;
+ }
+ }
+
/// Test if this node has a post-isel opcode, directly
/// corresponding to a MachineInstr opcode.
bool isMachineOpcode() const { return NodeType < 0; }
diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h
index 71ea82b6a9ab..68ad09982202 100644
--- a/include/llvm/DebugInfo/CodeView/CVRecord.h
+++ b/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -14,6 +14,7 @@
#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
@@ -50,6 +51,13 @@ public:
Optional<uint32_t> Hash;
};
+template <typename Kind> struct RemappedRecord {
+ explicit RemappedRecord(const CVRecord<Kind> &R) : OriginalRecord(R) {}
+
+ CVRecord<Kind> OriginalRecord;
+ SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings;
+};
+
} // end namespace codeview
template <typename Kind>
diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
index 4bc8fbefd5d8..70ccc867cd38 100644
--- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
+++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
@@ -46,6 +46,7 @@ Error visitMemberRecordStream(ArrayRef<uint8_t> FieldList,
TypeVisitorCallbacks &Callbacks);
Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks,
+ VisitorDataSource Source = VDS_BytesPresent,
TypeServerHandler *TS = nullptr);
Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks,
TypeServerHandler *TS = nullptr);
diff --git a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
index 2142d4a2dec7..a9c5cf42fc5b 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
@@ -40,6 +40,17 @@ class TypeDeserializer : public TypeVisitorCallbacks {
public:
TypeDeserializer() = default;
+ template <typename T> static Error deserializeAs(CVType &CVT, T &Record) {
+ MappingInfo I(CVT.content());
+ if (auto EC = I.Mapping.visitTypeBegin(CVT))
+ return EC;
+ if (auto EC = I.Mapping.visitKnownRecord(CVT, Record))
+ return EC;
+ if (auto EC = I.Mapping.visitTypeEnd(CVT))
+ return EC;
+ return Error::success();
+ }
+
Error visitTypeBegin(CVType &Record) override {
assert(!Mapping && "Already in a type mapping!");
Mapping = llvm::make_unique<MappingInfo>(Record.content());
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
new file mode 100644
index 000000000000..82ceb5038316
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
@@ -0,0 +1,33 @@
+//===- TypeIndexDiscovery.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_TYPEINDEXDISCOVERY_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+enum class TiRefKind { TypeRef, IndexRef };
+struct TiReference {
+ TiRefKind Kind;
+ uint32_t Offset;
+ uint32_t Count;
+};
+
+void discoverTypeIndices(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TiReference> &Refs);
+void discoverTypeIndices(const CVType &Type,
+ SmallVectorImpl<TiReference> &Refs);
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h
index 1f10872c8768..92745ebfcded 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -35,6 +35,7 @@ using support::ulittle16_t;
using support::ulittle32_t;
typedef CVRecord<TypeLeafKind> CVType;
+typedef RemappedRecord<TypeLeafKind> RemappedType;
struct CVMemberRecord {
TypeLeafKind Kind;
@@ -278,15 +279,9 @@ public:
Attrs(calcAttrs(PK, PM, PO, Size)) {}
PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM,
- PointerOptions PO, uint8_t Size,
- const MemberPointerInfo &Member)
+ PointerOptions PO, uint8_t Size, const MemberPointerInfo &MPI)
: TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
- Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(Member) {}
-
- PointerRecord(TypeIndex ReferentType, uint32_t Attrs,
- const MemberPointerInfo &Member)
- : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
- Attrs(Attrs), MemberInfo(Member) {}
+ Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {}
TypeIndex getReferentType() const { return ReferentType; }
diff --git a/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
index 6dad98247136..435c43f7edcb 100644
--- a/include/llvm/DebugInfo/CodeView/TypeSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
@@ -17,7 +17,6 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
@@ -26,6 +25,8 @@ namespace llvm {
namespace codeview {
+class TypeHasher;
+
class TypeSerializer : public TypeVisitorCallbacks {
struct SubRecord {
SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {}
@@ -45,14 +46,13 @@ class TypeSerializer : public TypeVisitorCallbacks {
}
};
- typedef SmallVector<MutableArrayRef<uint8_t>, 2> RecordList;
+ typedef SmallVector<MutableArrayRef<uint8_t>, 2> MutableRecordList;
static constexpr uint8_t ContinuationLength = 8;
BumpPtrAllocator &RecordStorage;
RecordSegment CurrentSegment;
- RecordList FieldListSegments;
+ MutableRecordList FieldListSegments;
- TypeIndex LastTypeIndex;
Optional<TypeLeafKind> TypeKind;
Optional<TypeLeafKind> MemberKind;
std::vector<uint8_t> RecordBuffer;
@@ -60,28 +60,35 @@ class TypeSerializer : public TypeVisitorCallbacks {
BinaryStreamWriter Writer;
TypeRecordMapping Mapping;
- RecordList SeenRecords;
- StringMap<TypeIndex> HashedRecords;
+ /// Private type record hashing implementation details are handled here.
+ std::unique_ptr<TypeHasher> Hasher;
+
+ /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
+ SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
+
+ /// Temporary storage that we use to copy a record's data while re-writing
+ /// its type indices.
+ SmallVector<uint8_t, 256> RemapStorage;
+
+ TypeIndex nextTypeIndex() const;
bool isInFieldList() const;
- TypeIndex calcNextTypeIndex() const;
- TypeIndex incrementTypeIndex();
MutableArrayRef<uint8_t> getCurrentSubRecordData();
MutableArrayRef<uint8_t> getCurrentRecordData();
Error writeRecordPrefix(TypeLeafKind Kind);
- TypeIndex insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record);
- TypeIndex insertRecordBytesWithCopy(CVType &Record,
- MutableArrayRef<uint8_t> Data);
Expected<MutableArrayRef<uint8_t>>
addPadding(MutableArrayRef<uint8_t> Record);
public:
- explicit TypeSerializer(BumpPtrAllocator &Storage);
+ explicit TypeSerializer(BumpPtrAllocator &Storage, bool Hash = true);
+ ~TypeSerializer();
+
+ void reset();
- ArrayRef<MutableArrayRef<uint8_t>> records() const;
- TypeIndex getLastTypeIndex() const;
- TypeIndex insertRecordBytes(MutableArrayRef<uint8_t> Record);
+ ArrayRef<ArrayRef<uint8_t>> records() const;
+ TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
+ TypeIndex insertRecord(const RemappedType &Record);
Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
Error visitTypeBegin(CVType &Record) override;
diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index 65bcf9812e68..3ad2b4e9c92f 100644
--- a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -22,12 +22,75 @@ class TypeIndex;
class TypeServerHandler;
class TypeTableBuilder;
-/// Merges one type stream into another. Returns true on success.
-Error mergeTypeStreams(TypeTableBuilder &DestIdStream,
- TypeTableBuilder &DestTypeStream,
+/// \brief Merge one set of type records into another. This method assumes
+/// that all records are type records, and there are no Id records present.
+///
+/// \param Dest The table to store the re-written type records into.
+///
+/// \param SourceToDest A vector, indexed by the TypeIndex in the source
+/// type stream, that contains the index of the corresponding type record
+/// in the destination stream.
+///
+/// \param Handler (optional) If non-null, an interface that gets invoked
+/// to handle type server records.
+///
+/// \param Types The collection of types to merge in.
+///
+/// \returns Error::success() if the operation succeeded, otherwise an
+/// appropriate error code.
+Error mergeTypeRecords(TypeTableBuilder &Dest,
SmallVectorImpl<TypeIndex> &SourceToDest,
TypeServerHandler *Handler, const CVTypeArray &Types);
+/// \brief Merge one set of id records into another. This method assumes
+/// that all records are id records, and there are no Type records present.
+/// However, since Id records can refer back to Type records, this method
+/// assumes that the referenced type records have also been merged into
+/// another type stream (for example using the above method), and accepts
+/// the mapping from source to dest for that stream so that it can re-write
+/// the type record mappings accordingly.
+///
+/// \param Dest The table to store the re-written id records into.
+///
+/// \param Types The mapping to use for the type records that these id
+/// records refer to.
+///
+/// \param SourceToDest A vector, indexed by the TypeIndex in the source
+/// id stream, that contains the index of the corresponding id record
+/// in the destination stream.
+///
+/// \param Ids The collection of id records to merge in.
+///
+/// \returns Error::success() if the operation succeeded, otherwise an
+/// appropriate error code.
+Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Ids);
+
+/// \brief Merge a unified set of type and id records, splitting them into
+/// separate output streams.
+///
+/// \param DestIds The table to store the re-written id records into.
+///
+/// \param DestTypes the table to store the re-written type records into.
+///
+/// \param SourceToDest A vector, indexed by the TypeIndex in the source
+/// id stream, that contains the index of the corresponding id record
+/// in the destination stream.
+///
+/// \param Handler (optional) If non-null, an interface that gets invoked
+/// to handle type server records.
+///
+/// \param IdsAndTypes The collection of id records to merge in.
+///
+/// \returns Error::success() if the operation succeeded, otherwise an
+/// appropriate error code.
+Error mergeTypeAndIdRecords(TypeTableBuilder &DestIds,
+ TypeTableBuilder &DestTypes,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ TypeServerHandler *Handler,
+ const CVTypeArray &IdsAndTypes);
+
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
index 102bee4b0801..7bdc9ecb20cf 100644
--- a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
+++ b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
@@ -64,10 +64,14 @@ public:
return *ExpectedIndex;
}
- TypeIndex writeSerializedRecord(MutableArrayRef<uint8_t> Record) {
+ TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) {
return Serializer.insertRecordBytes(Record);
}
+ TypeIndex writeSerializedRecord(const RemappedType &Record) {
+ return Serializer.insertRecord(Record);
+ }
+
template <typename TFunc> void ForEachRecord(TFunc Func) {
uint32_t Index = TypeIndex::FirstNonSimpleIndex;
@@ -77,23 +81,24 @@ public:
}
}
- ArrayRef<MutableArrayRef<uint8_t>> records() const {
- return Serializer.records();
- }
+ ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); }
};
class FieldListRecordBuilder {
TypeTableBuilder &TypeTable;
+ BumpPtrAllocator Allocator;
TypeSerializer TempSerializer;
CVType Type;
public:
explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
- : TypeTable(TypeTable), TempSerializer(TypeTable.getAllocator()) {
+ : TypeTable(TypeTable), TempSerializer(Allocator, false) {
Type.Type = TypeLeafKind::LF_FIELDLIST;
}
void begin() {
+ TempSerializer.reset();
+
if (auto EC = TempSerializer.visitTypeBegin(Type))
consumeError(std::move(EC));
}
@@ -109,23 +114,19 @@ public:
consumeError(std::move(EC));
}
- TypeIndex end() {
+ TypeIndex end(bool Write) {
+ TypeIndex Index;
if (auto EC = TempSerializer.visitTypeEnd(Type)) {
consumeError(std::move(EC));
return TypeIndex();
}
- TypeIndex Index;
- for (auto Record : TempSerializer.records()) {
- Index = TypeTable.writeSerializedRecord(Record);
+ if (Write) {
+ for (auto Record : TempSerializer.records())
+ Index = TypeTable.writeSerializedRecord(Record);
}
- return Index;
- }
- /// Stop building the record.
- void reset() {
- if (auto EC = TempSerializer.visitTypeEnd(Type))
- consumeError(std::move(EC));
+ return Index;
}
};
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
index 7de562a19a74..42b62ba2b6ce 100644
--- a/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
+++ b/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
@@ -18,7 +18,7 @@ namespace codeview {
class TypeTableCollection : public TypeCollection {
public:
- explicit TypeTableCollection(ArrayRef<MutableArrayRef<uint8_t>> Records);
+ explicit TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records);
Optional<TypeIndex> getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
@@ -33,7 +33,7 @@ private:
bool hasCapacityFor(TypeIndex Index) const;
void ensureTypeExists(TypeIndex Index);
- ArrayRef<MutableArrayRef<uint8_t>> Records;
+ ArrayRef<ArrayRef<uint8_t>> Records;
TypeDatabase Database;
};
}
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index d3a63edf10ff..7fa68f3f2314 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -46,7 +46,8 @@ class raw_ostream;
/// Reads a value from data extractor and applies a relocation to the result if
/// one exists for the given offset.
uint64_t getRelocatedValue(const DataExtractor &Data, uint32_t Size,
- uint32_t *Off, const RelocAddrMap *Relocs);
+ uint32_t *Off, const RelocAddrMap *Relocs,
+ uint64_t *SecNdx = nullptr);
/// DWARFContext
/// This data structure is the top level entity that deals with dwarf debug
@@ -71,6 +72,14 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
std::unique_ptr<DWARFDebugLocDWO> LocDWO;
+ struct DWOFile {
+ object::OwningBinary<object::ObjectFile> File;
+ std::unique_ptr<DWARFContext> Context;
+ };
+ StringMap<std::weak_ptr<DWOFile>> DWOFiles;
+ std::weak_ptr<DWOFile> DWP;
+ bool CheckedForDWP = false;
+
/// Read compile units from the debug_info section (if necessary)
/// and store them in CUs.
void parseCompileUnits();
@@ -165,6 +174,8 @@ public:
return DWOCUs[index].get();
}
+ DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
+
/// Get a DIE given an exact offset.
DWARFDie getDIEForOffset(uint32_t Offset);
@@ -206,6 +217,7 @@ public:
DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
+ virtual StringRef getFileName() const = 0;
virtual bool isLittleEndian() const = 0;
virtual uint8_t getAddressSize() const = 0;
virtual const DWARFSection &getInfoSection() = 0;
@@ -248,6 +260,8 @@ public:
return version == 2 || version == 3 || version == 4 || version == 5;
}
+ std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
+
private:
/// Return the compile unit that includes an offset (relative to .debug_info).
DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
@@ -263,6 +277,7 @@ private:
class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
+ StringRef FileName;
bool IsLittleEndian;
uint8_t AddressSize;
DWARFSection InfoSection;
@@ -316,6 +331,7 @@ public:
uint8_t AddrSize,
bool isLittleEndian = sys::IsLittleEndianHost);
+ StringRef getFileName() const override { return FileName; }
bool isLittleEndian() const override { return IsLittleEndian; }
uint8_t getAddressSize() const override { return AddressSize; }
const DWARFSection &getInfoSection() override { return InfoSection; }
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index 95ec1be62a79..b436711ae6ed 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -25,6 +25,7 @@ class raw_ostream;
struct DWARFAddressRange {
uint64_t LowPC;
uint64_t HighPC;
+ uint64_t SectionIndex;
};
/// DWARFAddressRangesVector - represents a set of absolute address ranges.
@@ -44,6 +45,8 @@ public:
/// address past the end of the address range. The ending address must
/// be greater than or equal to the beginning address.
uint64_t EndAddress;
+ /// A section index this range belongs to.
+ uint64_t SectionIndex;
/// The end of any given range list is marked by an end of list entry,
/// which consists of a 0 for the beginning address offset
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h
index ca94a90fabfc..fa41b9e293c0 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -195,7 +195,8 @@ public:
/// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
/// Returns true if both attributes are present.
- bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const;
+ bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC,
+ uint64_t &SectionIndex) const;
/// Get the address ranges for this DIE.
///
diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index a30e0be9c3c3..3a781dde8929 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -47,6 +47,7 @@ private:
const char *cstr;
};
const uint8_t *data = nullptr;
+ uint64_t SectionIndex; /// Section index for reference forms.
};
dwarf::Form Form; /// Form for this value.
@@ -58,6 +59,7 @@ public:
dwarf::Form getForm() const { return Form; }
uint64_t getRawUValue() const { return Value.uval; }
+ uint64_t getSectionIndex() const { return Value.SectionIndex; }
void setForm(dwarf::Form F) { Form = F; }
void setUValue(uint64_t V) { Value.uval = V; }
void setSValue(int64_t V) { Value.sval = V; }
diff --git a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
index fabacc0abcea..f143de334737 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
@@ -16,7 +16,10 @@
namespace llvm {
+/// RelocAddrEntry contains relocated value and section index.
+/// Section index is -1LL if relocation points to absolute symbol.
struct RelocAddrEntry {
+ uint64_t SectionIndex;
uint64_t Value;
};
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index ae7fd24ce5bb..d0f7bd0d623f 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -143,17 +143,7 @@ class DWARFUnit {
typedef iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>
die_iterator_range;
- class DWOHolder {
- object::OwningBinary<object::ObjectFile> DWOFile;
- std::unique_ptr<DWARFContext> DWOContext;
- DWARFUnit *DWOU = nullptr;
-
- public:
- DWOHolder(StringRef DWOPath, uint64_t DWOId);
-
- DWARFUnit *getUnit() const { return DWOU; }
- };
- std::unique_ptr<DWOHolder> DWO;
+ std::shared_ptr<DWARFUnit> DWO;
const DWARFUnitIndex::Entry *IndexEntry;
diff --git a/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/include/llvm/DebugInfo/MSF/MappedBlockStream.h
index c91f6f725c80..d68f5f70c83e 100644
--- a/include/llvm/DebugInfo/MSF/MappedBlockStream.h
+++ b/include/llvm/DebugInfo/MSF/MappedBlockStream.h
@@ -43,8 +43,8 @@ class MappedBlockStream : public BinaryStream {
friend class WritableMappedBlockStream;
public:
static std::unique_ptr<MappedBlockStream>
- createStream(uint32_t BlockSize, uint32_t NumBlocks,
- const MSFStreamLayout &Layout, BinaryStreamRef MsfData);
+ createStream(uint32_t BlockSize, const MSFStreamLayout &Layout,
+ BinaryStreamRef MsfData);
static std::unique_ptr<MappedBlockStream>
createIndexedStream(const MSFLayout &Layout, BinaryStreamRef MsfData,
@@ -74,12 +74,11 @@ public:
void invalidateCache();
uint32_t getBlockSize() const { return BlockSize; }
- uint32_t getNumBlocks() const { return NumBlocks; }
+ uint32_t getNumBlocks() const { return StreamLayout.Blocks.size(); }
uint32_t getStreamLength() const { return StreamLayout.Length; }
protected:
- MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
- const MSFStreamLayout &StreamLayout,
+ MappedBlockStream(uint32_t BlockSize, const MSFStreamLayout &StreamLayout,
BinaryStreamRef MsfData);
private:
@@ -91,7 +90,6 @@ private:
ArrayRef<uint8_t> &Buffer);
const uint32_t BlockSize;
- const uint32_t NumBlocks;
const MSFStreamLayout StreamLayout;
BinaryStreamRef MsfData;
@@ -103,8 +101,8 @@ private:
class WritableMappedBlockStream : public WritableBinaryStream {
public:
static std::unique_ptr<WritableMappedBlockStream>
- createStream(uint32_t BlockSize, uint32_t NumBlocks,
- const MSFStreamLayout &Layout, WritableBinaryStreamRef MsfData);
+ createStream(uint32_t BlockSize, const MSFStreamLayout &Layout,
+ WritableBinaryStreamRef MsfData);
static std::unique_ptr<WritableMappedBlockStream>
createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData,
@@ -139,7 +137,7 @@ public:
uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); }
protected:
- WritableMappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks,
+ WritableMappedBlockStream(uint32_t BlockSize,
const MSFStreamLayout &StreamLayout,
WritableBinaryStreamRef MsfData);
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index bcac182e2145..e116f314ac0e 100644
--- a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -82,6 +82,7 @@ private:
Error finalize();
uint32_t calculateModiSubstreamSize() const;
+ uint32_t calculateNamesOffset() const;
uint32_t calculateSectionContribsStreamSize() const;
uint32_t calculateSectionMapStreamSize() const;
uint32_t calculateFileInfoSubstreamSize() const;
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h b/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
index bfd38b6c80ec..196ba4d6ffbd 100644
--- a/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h
@@ -11,8 +11,7 @@
#define LLVM_DEBUGINFO_PDB_PDBTYPESERVERHANDLER_H
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
@@ -39,7 +38,7 @@ private:
bool RevisitAlways;
std::unique_ptr<NativeSession> Session;
- SmallVector<SmallString<64>, 4> SearchPaths;
+ StringSet<> SearchPaths;
};
}
}
diff --git a/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/include/llvm/DebugInfo/PDB/Native/TpiStream.h
index c5549983ed43..17fba9991c2e 100644
--- a/include/llvm/DebugInfo/PDB/Native/TpiStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/TpiStream.h
@@ -21,6 +21,9 @@
#include "llvm/Support/Error.h"
namespace llvm {
+namespace codeview {
+class LazyRandomTypeCollection;
+}
namespace msf {
class MappedBlockStream;
}
@@ -53,12 +56,16 @@ public:
codeview::CVTypeRange types(bool *HadError) const;
const codeview::CVTypeArray &typeArray() const { return TypeRecords; }
+ codeview::LazyRandomTypeCollection &typeCollection() { return *Types; }
+
Error commit();
private:
const PDBFile &Pdb;
std::unique_ptr<msf::MappedBlockStream> Stream;
+ std::unique_ptr<codeview::LazyRandomTypeCollection> Types;
+
codeview::CVTypeArray TypeRecords;
std::unique_ptr<BinaryStream> HashStream;
diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h
index d4a896c01867..ace309ed95a4 100644
--- a/include/llvm/IR/Attributes.h
+++ b/include/llvm/IR/Attributes.h
@@ -322,7 +322,7 @@ template <> struct DenseMapInfo<AttributeSet> {
/// the AttributeList object. The function attributes are at index
/// `AttributeList::FunctionIndex', the return value is at index
/// `AttributeList::ReturnIndex', and the attributes for the parameters start at
-/// index `1'.
+/// index `AttributeList::FirstArgIndex'.
class AttributeList {
public:
enum AttrIndex : unsigned {
@@ -347,8 +347,8 @@ public:
/// \brief Create an AttributeList with the specified parameters in it.
static AttributeList get(LLVMContext &C,
ArrayRef<std::pair<unsigned, Attribute>> Attrs);
- static AttributeList
- get(LLVMContext &C, ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
+ static AttributeList get(LLVMContext &C,
+ ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
/// \brief Create an AttributeList from attribute sets for a function, its
/// return value, and all of its arguments.
@@ -356,13 +356,11 @@ public:
AttributeSet RetAttrs,
ArrayRef<AttributeSet> ArgAttrs);
- static AttributeList
- getImpl(LLVMContext &C,
- ArrayRef<std::pair<unsigned, AttributeSet>> Attrs);
-
private:
explicit AttributeList(AttributeListImpl *LI) : pImpl(LI) {}
+ static AttributeList getImpl(LLVMContext &C, ArrayRef<AttributeSet> AttrSets);
+
public:
AttributeList() = default;
@@ -521,39 +519,31 @@ public:
/// \brief Return the attributes at the index as a string.
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
- using iterator = ArrayRef<Attribute>::iterator;
+ //===--------------------------------------------------------------------===//
+ // AttributeList Introspection
+ //===--------------------------------------------------------------------===//
+
+ typedef const AttributeSet *iterator;
+ iterator begin() const;
+ iterator end() const;
+
+ unsigned getNumAttrSets() const;
- iterator begin(unsigned Slot) const;
- iterator end(unsigned Slot) const;
+ /// Use these to iterate over the valid attribute indices.
+ unsigned index_begin() const { return AttributeList::FunctionIndex; }
+ unsigned index_end() const { return getNumAttrSets() - 1; }
/// operator==/!= - Provide equality predicates.
bool operator==(const AttributeList &RHS) const { return pImpl == RHS.pImpl; }
bool operator!=(const AttributeList &RHS) const { return pImpl != RHS.pImpl; }
- //===--------------------------------------------------------------------===//
- // AttributeList Introspection
- //===--------------------------------------------------------------------===//
-
/// \brief Return a raw pointer that uniquely identifies this attribute list.
void *getRawPointer() const {
return pImpl;
}
/// \brief Return true if there are no attributes.
- bool isEmpty() const {
- return getNumSlots() == 0;
- }
-
- /// \brief Return the number of slots used in this attribute list. This is
- /// the number of arguments that have an attribute set on them (including the
- /// function itself).
- unsigned getNumSlots() const;
-
- /// \brief Return the index for the given slot.
- unsigned getSlotIndex(unsigned Slot) const;
-
- /// \brief Return the attributes at the given slot.
- AttributeSet getSlotAttributes(unsigned Slot) const;
+ bool isEmpty() const { return pImpl == nullptr; }
void dump() const;
};
diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h
index c917b1f2cada..235cb57cfd09 100644
--- a/include/llvm/IR/BasicBlock.h
+++ b/include/llvm/IR/BasicBlock.h
@@ -33,6 +33,7 @@ class Function;
class LandingPadInst;
class LLVMContext;
class Module;
+class PHINode;
class TerminatorInst;
class ValueSymbolTable;
@@ -261,6 +262,50 @@ public:
inline const Instruction &back() const { return InstList.back(); }
inline Instruction &back() { return InstList.back(); }
+ /// Iterator to walk just the phi nodes in the basic block.
+ template <typename PHINodeT = PHINode, typename BBIteratorT = iterator>
+ class phi_iterator_impl
+ : public iterator_facade_base<phi_iterator_impl<PHINodeT, BBIteratorT>,
+ std::forward_iterator_tag, PHINodeT> {
+ friend BasicBlock;
+
+ PHINodeT *PN;
+
+ phi_iterator_impl(PHINodeT *PN) : PN(PN) {}
+
+ public:
+ // Allow default construction to build variables, but this doesn't build
+ // a useful iterator.
+ phi_iterator_impl() = default;
+
+ // Allow conversion between instantiations where valid.
+ template <typename PHINodeU, typename BBIteratorU>
+ phi_iterator_impl(const phi_iterator_impl<PHINodeU, BBIteratorU> &Arg)
+ : PN(Arg.PN) {}
+
+ bool operator==(const phi_iterator_impl &Arg) const { return PN == Arg.PN; }
+
+ PHINodeT &operator*() const { return *PN; }
+
+ using phi_iterator_impl::iterator_facade_base::operator++;
+ phi_iterator_impl &operator++() {
+ assert(PN && "Cannot increment the end iterator!");
+ PN = dyn_cast<PHINodeT>(std::next(BBIteratorT(PN)));
+ return *this;
+ }
+ };
+ typedef phi_iterator_impl<> phi_iterator;
+ typedef phi_iterator_impl<const PHINode, BasicBlock::const_iterator>
+ const_phi_iterator;
+
+ /// Returns a range that iterates over the phis in the basic block.
+ ///
+ /// Note that this cannot be used with basic blocks that have no terminator.
+ iterator_range<const_phi_iterator> phis() const {
+ return const_cast<BasicBlock *>(this)->phis();
+ }
+ iterator_range<phi_iterator> phis();
+
/// \brief Return the underlying instruction list container.
///
/// Currently you need to access the underlying instruction list container
diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h
index 05e3315cbab2..2ae98d9e35b0 100644
--- a/include/llvm/IR/IntrinsicInst.h
+++ b/include/llvm/IR/IntrinsicInst.h
@@ -171,6 +171,7 @@ namespace llvm {
ebStrict
};
+ bool isUnaryOp() const;
RoundingMode getRoundingMode() const;
ExceptionBehavior getExceptionBehavior() const;
@@ -182,6 +183,18 @@ namespace llvm {
case Intrinsic::experimental_constrained_fmul:
case Intrinsic::experimental_constrained_fdiv:
case Intrinsic::experimental_constrained_frem:
+ case Intrinsic::experimental_constrained_sqrt:
+ case Intrinsic::experimental_constrained_pow:
+ case Intrinsic::experimental_constrained_powi:
+ case Intrinsic::experimental_constrained_sin:
+ case Intrinsic::experimental_constrained_cos:
+ case Intrinsic::experimental_constrained_exp:
+ case Intrinsic::experimental_constrained_exp2:
+ case Intrinsic::experimental_constrained_log:
+ case Intrinsic::experimental_constrained_log10:
+ case Intrinsic::experimental_constrained_log2:
+ case Intrinsic::experimental_constrained_rint:
+ case Intrinsic::experimental_constrained_nearbyint:
return true;
default: return false;
}
diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td
index 19f6045568f4..291d16fb0d9b 100644
--- a/include/llvm/IR/Intrinsics.td
+++ b/include/llvm/IR/Intrinsics.td
@@ -489,8 +489,64 @@ let IntrProperties = [IntrInaccessibleMemOnly] in {
LLVMMatchType<0>,
llvm_metadata_ty,
llvm_metadata_ty ]>;
+
+ // These intrinsics are sensitive to the rounding mode so we need constrained
+ // versions of each of them. When strict rounding and exception control are
+ // not required the non-constrained versions of these intrinsics should be
+ // used.
+ def int_experimental_constrained_sqrt : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_powi : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_i32_ty,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_sin : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_cos : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_pow : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_log : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_log10: Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_log2 : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_exp : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_exp2 : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_rint : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
+ def int_experimental_constrained_nearbyint : Intrinsic<[ llvm_anyfloat_ty ],
+ [ LLVMMatchType<0>,
+ llvm_metadata_ty,
+ llvm_metadata_ty ]>;
}
-// FIXME: Add intrinsic for fcmp, fptrunc, fpext, fptoui and fptosi.
+// FIXME: Add intrinsics for fcmp, fptrunc, fpext, fptoui and fptosi.
+// FIXME: Add intrinsics for fabs, copysign, floor, ceil, trunc and round?
//===------------------------- Expect Intrinsics --------------------------===//
diff --git a/include/llvm/IR/IntrinsicsAMDGPU.td b/include/llvm/IR/IntrinsicsAMDGPU.td
index d7413fe9e56f..e1928546607a 100644
--- a/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -566,6 +566,16 @@ def int_amdgcn_s_getreg :
[IntrReadMem, IntrSpeculatable]
>;
+// int_amdgcn_s_getpc is provided to allow a specific style of position
+// independent code to determine the high part of its address when it is
+// known (through convention) that the code and any data of interest does
+// not cross a 4Gb address boundary. Use for any other purpose may not
+// produce the desired results as optimizations may cause code movement,
+// especially as we explicitly use IntrNoMem to allow optimizations.
+def int_amdgcn_s_getpc :
+ GCCBuiltin<"__builtin_amdgcn_s_getpc">,
+ Intrinsic<[llvm_i64_ty], [], [IntrNoMem, IntrSpeculatable]>;
+
// __builtin_amdgcn_interp_mov <param>, <attr_chan>, <attr>, <m0>
// param values: 0 = P10, 1 = P20, 2 = P0
def int_amdgcn_interp_mov :
diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h
index 92f701e01ff3..3c753260190e 100644
--- a/include/llvm/IR/Metadata.h
+++ b/include/llvm/IR/Metadata.h
@@ -1223,6 +1223,7 @@ public:
// FIXME: Fix callers and remove condition on N.
unsigned size() const { return N ? N->getNumOperands() : 0u; }
+ bool empty() const { return N ? N->getNumOperands() == 0 : true; }
T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); }
// FIXME: Fix callers and remove condition on N.
diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h
index 3024d9e27a2f..5e1f680c5b36 100644
--- a/include/llvm/IR/Module.h
+++ b/include/llvm/IR/Module.h
@@ -139,9 +139,12 @@ public:
/// during the append operation.
AppendUnique = 6,
+ /// Takes the max of the two values, which are required to be integers.
+ Max = 7,
+
// Markers:
ModFlagBehaviorFirstVal = Error,
- ModFlagBehaviorLastVal = AppendUnique
+ ModFlagBehaviorLastVal = Max
};
/// Checks if Metadata represents a valid ModFlagBehavior, and stores the
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 3df5244a0bd6..3ca21c15577b 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -144,6 +144,7 @@ void initializeGCMachineCodeAnalysisPass(PassRegistry&);
void initializeGCModuleInfoPass(PassRegistry&);
void initializeGCOVProfilerLegacyPassPass(PassRegistry&);
void initializeGVNHoistLegacyPassPass(PassRegistry&);
+void initializeGVNSinkLegacyPassPass(PassRegistry&);
void initializeGVNLegacyPassPass(PassRegistry&);
void initializeGlobalDCELegacyPassPass(PassRegistry&);
void initializeGlobalMergePass(PassRegistry&);
@@ -193,6 +194,7 @@ void initializeLiveVariablesPass(PassRegistry&);
void initializeLoadCombinePass(PassRegistry&);
void initializeLoadStoreVectorizerPass(PassRegistry&);
void initializeLoaderPassPass(PassRegistry&);
+void initializeLocalizerPass(PassRegistry&);
void initializeLocalStackSlotPassPass(PassRegistry&);
void initializeLoopAccessLegacyAnalysisPass(PassRegistry&);
void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&);
diff --git a/include/llvm/LTO/Config.h b/include/llvm/LTO/Config.h
index ede6637dfa4d..5ba8492db8f5 100644
--- a/include/llvm/LTO/Config.h
+++ b/include/llvm/LTO/Config.h
@@ -39,7 +39,7 @@ struct Config {
std::string CPU;
TargetOptions Options;
std::vector<std::string> MAttrs;
- Reloc::Model RelocModel = Reloc::PIC_;
+ Optional<Reloc::Model> RelocModel = Reloc::PIC_;
CodeModel::Model CodeModel = CodeModel::Default;
CodeGenOpt::Level CGOptLevel = CodeGenOpt::Default;
TargetMachine::CodeGenFileType CGFileType = TargetMachine::CGFT_ObjectFile;
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index cf5d93ee9ed7..3f5a233c1ee1 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -95,9 +95,7 @@ public:
return TypeID > ID_StartObjects && TypeID < ID_EndObjects;
}
- bool isSymbolic() const {
- return isIR() || isObject();
- }
+ bool isSymbolic() const { return isIR() || isObject() || isCOFFImportFile(); }
bool isArchive() const {
return TypeID == ID_Archive;
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index 8b9b49737170..dafd1a43cb59 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -782,6 +782,7 @@ protected:
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h
index d8b58b8079fa..ef2abd8c52ce 100644
--- a/include/llvm/Object/ELFObjectFile.h
+++ b/include/llvm/Object/ELFObjectFile.h
@@ -235,6 +235,7 @@ protected:
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
@@ -646,6 +647,17 @@ uint64_t ELFObjectFile<ELFT>::getSectionAddress(DataRefImpl Sec) const {
}
template <class ELFT>
+uint64_t ELFObjectFile<ELFT>::getSectionIndex(DataRefImpl Sec) const {
+ auto SectionsOrErr = EF.sections();
+ handleAllErrors(std::move(SectionsOrErr.takeError()),
+ [](const ErrorInfoBase &) {
+ llvm_unreachable("unable to get section index");
+ });
+ const Elf_Shdr *First = SectionsOrErr->begin();
+ return getSection(Sec) - First;
+}
+
+template <class ELFT>
uint64_t ELFObjectFile<ELFT>::getSectionSize(DataRefImpl Sec) const {
return getSection(Sec)->sh_size;
}
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index 29553558f72f..a4356d5977b2 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -290,6 +290,7 @@ public:
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 9a7bc618ffd0..ea6a9049bc1b 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -95,6 +95,7 @@ public:
std::error_code getName(StringRef &Result) const;
uint64_t getAddress() const;
+ uint64_t getIndex() const;
uint64_t getSize() const;
std::error_code getContents(StringRef &Result) const;
@@ -222,6 +223,7 @@ protected:
virtual std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const = 0;
virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0;
+ virtual uint64_t getSectionIndex(DataRefImpl Sec) const = 0;
virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0;
virtual std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const = 0;
@@ -393,6 +395,10 @@ inline uint64_t SectionRef::getAddress() const {
return OwningObject->getSectionAddress(SectionPimpl);
}
+inline uint64_t SectionRef::getIndex() const {
+ return OwningObject->getSectionIndex(SectionPimpl);
+}
+
inline uint64_t SectionRef::getSize() const {
return OwningObject->getSectionSize(SectionPimpl);
}
diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h
index 86579b7c3e3a..348179860f3e 100644
--- a/include/llvm/Object/RelocVisitor.h
+++ b/include/llvm/Object/RelocVisitor.h
@@ -40,13 +40,13 @@ public:
// TODO: Should handle multiple applied relocations via either passing in the
// previously computed value or just count paired relocations as a single
// visit.
- uint64_t visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) {
+ uint64_t visit(uint32_t Rel, RelocationRef R, uint64_t Value = 0) {
if (isa<ELFObjectFileBase>(ObjToVisit))
- return visitELF(RelocType, R, Value);
+ return visitELF(Rel, R, Value);
if (isa<COFFObjectFile>(ObjToVisit))
- return visitCOFF(RelocType, R, Value);
+ return visitCOFF(Rel, R, Value);
if (isa<MachOObjectFile>(ObjToVisit))
- return visitMachO(RelocType, R, Value);
+ return visitMachO(Rel, R, Value);
HasError = true;
return 0;
@@ -58,214 +58,60 @@ private:
const ObjectFile &ObjToVisit;
bool HasError = false;
- uint64_t visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
+ uint64_t visitELF(uint32_t Rel, RelocationRef R, uint64_t Value) {
if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file
switch (ObjToVisit.getArch()) {
case Triple::x86_64:
- switch (RelocType) {
- case ELF::R_X86_64_NONE:
- return visitELF_X86_64_NONE(R);
- case ELF::R_X86_64_64:
- return visitELF_X86_64_64(R, Value);
- case ELF::R_X86_64_PC32:
- return visitELF_X86_64_PC32(R, Value);
- case ELF::R_X86_64_32:
- return visitELF_X86_64_32(R, Value);
- case ELF::R_X86_64_32S:
- return visitELF_X86_64_32S(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitX86_64(Rel, R, Value);
case Triple::aarch64:
case Triple::aarch64_be:
- switch (RelocType) {
- case ELF::R_AARCH64_ABS32:
- return visitELF_AARCH64_ABS32(R, Value);
- case ELF::R_AARCH64_ABS64:
- return visitELF_AARCH64_ABS64(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitAarch64(Rel, R, Value);
case Triple::bpfel:
case Triple::bpfeb:
- switch (RelocType) {
- case ELF::R_BPF_64_64:
- return visitELF_BPF_64_64(R, Value);
- case ELF::R_BPF_64_32:
- return visitELF_BPF_64_32(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitBpf(Rel, R, Value);
case Triple::mips64el:
case Triple::mips64:
- switch (RelocType) {
- case ELF::R_MIPS_32:
- return visitELF_MIPS64_32(R, Value);
- case ELF::R_MIPS_64:
- return visitELF_MIPS64_64(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitMips64(Rel, R, Value);
case Triple::ppc64le:
case Triple::ppc64:
- switch (RelocType) {
- case ELF::R_PPC64_ADDR32:
- return visitELF_PPC64_ADDR32(R, Value);
- case ELF::R_PPC64_ADDR64:
- return visitELF_PPC64_ADDR64(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitPPC64(Rel, R, Value);
case Triple::systemz:
- switch (RelocType) {
- case ELF::R_390_32:
- return visitELF_390_32(R, Value);
- case ELF::R_390_64:
- return visitELF_390_64(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitSystemz(Rel, R, Value);
case Triple::sparcv9:
- switch (RelocType) {
- case ELF::R_SPARC_32:
- case ELF::R_SPARC_UA32:
- return visitELF_SPARCV9_32(R, Value);
- case ELF::R_SPARC_64:
- case ELF::R_SPARC_UA64:
- return visitELF_SPARCV9_64(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitSparc64(Rel, R, Value);
case Triple::amdgcn:
- switch (RelocType) {
- case ELF::R_AMDGPU_ABS32:
- return visitELF_AMDGPU_ABS32(R, Value);
- case ELF::R_AMDGPU_ABS64:
- return visitELF_AMDGPU_ABS64(R, Value);
- default:
- HasError = true;
- return 0;
- }
+ return visitAmdgpu(Rel, R, Value);
default:
HasError = true;
return 0;
}
- } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file
- switch (ObjToVisit.getArch()) {
- case Triple::x86:
- switch (RelocType) {
- case ELF::R_386_NONE:
- return visitELF_386_NONE(R);
- case ELF::R_386_32:
- return visitELF_386_32(R, Value);
- case ELF::R_386_PC32:
- return visitELF_386_PC32(R, Value);
- default:
- HasError = true;
- return 0;
- }
- case Triple::ppc:
- switch (RelocType) {
- case ELF::R_PPC_ADDR32:
- return visitELF_PPC_ADDR32(R, Value);
- default:
- HasError = true;
- return 0;
- }
- case Triple::arm:
- case Triple::armeb:
- switch (RelocType) {
- default:
- HasError = true;
- return 0;
- case ELF::R_ARM_ABS32:
- return visitELF_ARM_ABS32(R, Value);
- }
- case Triple::lanai:
- switch (RelocType) {
- case ELF::R_LANAI_32:
- return visitELF_Lanai_32(R, Value);
- default:
- HasError = true;
- return 0;
- }
- case Triple::mipsel:
- case Triple::mips:
- switch (RelocType) {
- case ELF::R_MIPS_32:
- return visitELF_MIPS_32(R, Value);
- default:
- HasError = true;
- return 0;
- }
- case Triple::sparc:
- switch (RelocType) {
- case ELF::R_SPARC_32:
- case ELF::R_SPARC_UA32:
- return visitELF_SPARC_32(R, Value);
- default:
- HasError = true;
- return 0;
- }
- case Triple::hexagon:
- switch (RelocType) {
- case ELF::R_HEX_32:
- return visitELF_HEX_32(R, Value);
- default:
- HasError = true;
- return 0;
- }
- default:
- HasError = true;
- return 0;
- }
- } else {
- report_fatal_error("Invalid word size in object file");
}
- }
- uint64_t visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) {
- switch (ObjToVisit.getArch()) {
- case Triple::x86:
- switch (RelocType) {
- case COFF::IMAGE_REL_I386_SECREL:
- return visitCOFF_I386_SECREL(R, Value);
- case COFF::IMAGE_REL_I386_DIR32:
- return visitCOFF_I386_DIR32(R, Value);
- }
- break;
- case Triple::x86_64:
- switch (RelocType) {
- case COFF::IMAGE_REL_AMD64_SECREL:
- return visitCOFF_AMD64_SECREL(R, Value);
- case COFF::IMAGE_REL_AMD64_ADDR64:
- return visitCOFF_AMD64_ADDR64(R, Value);
- }
- break;
- }
- HasError = true;
- return 0;
- }
+ // 32-bit object file
+ assert(ObjToVisit.getBytesInAddress() == 4 &&
+ "Invalid word size in object file");
- uint64_t visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) {
switch (ObjToVisit.getArch()) {
- default: break;
- case Triple::x86_64:
- switch (RelocType) {
- default: break;
- case MachO::X86_64_RELOC_UNSIGNED:
- return visitMACHO_X86_64_UNSIGNED(R, Value);
- }
+ case Triple::x86:
+ return visitX86(Rel, R, Value);
+ case Triple::ppc:
+ return visitPPC32(Rel, R, Value);
+ case Triple::arm:
+ case Triple::armeb:
+ return visitARM(Rel, R, Value);
+ case Triple::lanai:
+ return visitLanai(Rel, R, Value);
+ case Triple::mipsel:
+ case Triple::mips:
+ return visitMips32(Rel, R, Value);
+ case Triple::sparc:
+ return visitSparc32(Rel, R, Value);
+ case Triple::hexagon:
+ return visitHexagon(Rel, R, Value);
+ default:
+ HasError = true;
+ return 0;
}
- HasError = true;
- return 0;
}
int64_t getELFAddend(RelocationRef R) {
@@ -275,176 +121,193 @@ private:
return *AddendOrErr;
}
- /// Operations
-
- /// 386-ELF
- uint64_t visitELF_386_NONE(RelocationRef R) {
+ uint64_t visitX86_64(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_X86_64_NONE:
+ return 0;
+ case ELF::R_X86_64_64:
+ return Value + getELFAddend(R);
+ case ELF::R_X86_64_PC32:
+ return Value + getELFAddend(R) - R.getOffset();
+ case ELF::R_X86_64_32:
+ case ELF::R_X86_64_32S:
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
+ }
+ HasError = true;
return 0;
}
- // Ideally the Addend here will be the addend in the data for
- // the relocation. It's not actually the case for Rel relocations.
- uint64_t visitELF_386_32(RelocationRef R, uint64_t Value) {
- return Value;
- }
-
- uint64_t visitELF_386_PC32(RelocationRef R, uint64_t Value) {
- return Value - R.getOffset();
- }
-
- /// X86-64 ELF
- uint64_t visitELF_X86_64_NONE(RelocationRef R) {
+ uint64_t visitAarch64(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_AARCH64_ABS32: {
+ int64_t Res = Value + getELFAddend(R);
+ if (Res < INT32_MIN || Res > UINT32_MAX)
+ HasError = true;
+ return static_cast<uint32_t>(Res);
+ }
+ case ELF::R_AARCH64_ABS64:
+ return Value + getELFAddend(R);
+ }
+ HasError = true;
return 0;
}
- uint64_t visitELF_X86_64_64(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R);
- }
-
- uint64_t visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R) - R.getOffset();
- }
-
- uint64_t visitELF_X86_64_32(RelocationRef R, uint64_t Value) {
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- }
-
- uint64_t visitELF_X86_64_32S(RelocationRef R, uint64_t Value) {
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- }
-
- /// BPF ELF
- uint64_t visitELF_BPF_64_32(RelocationRef R, uint64_t Value) {
- return Value & 0xFFFFFFFF;
- }
-
- uint64_t visitELF_BPF_64_64(RelocationRef R, uint64_t Value) {
- return Value;
- }
-
- /// PPC64 ELF
- uint64_t visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) {
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- }
-
- uint64_t visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R);
- }
-
- /// PPC32 ELF
- uint64_t visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) {
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- }
-
- /// Lanai ELF
- uint64_t visitELF_Lanai_32(RelocationRef R, uint64_t Value) {
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- }
-
- /// MIPS ELF
- uint64_t visitELF_MIPS_32(RelocationRef R, uint64_t Value) {
- return Value & 0xFFFFFFFF;
- }
-
- /// MIPS64 ELF
- uint64_t visitELF_MIPS64_32(RelocationRef R, uint64_t Value) {
- return (Value + getELFAddend(R)) & 0xFFFFFFFF;
- }
-
- uint64_t visitELF_MIPS64_64(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R);
- }
-
- // AArch64 ELF
- uint64_t visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- int64_t Res = Value + Addend;
-
- // Overflow check allows for both signed and unsigned interpretation.
- if (Res < INT32_MIN || Res > UINT32_MAX)
- HasError = true;
-
- return static_cast<uint32_t>(Res);
- }
-
- uint64_t visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R);
+ uint64_t visitBpf(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_BPF_64_32:
+ return Value & 0xFFFFFFFF;
+ case ELF::R_BPF_64_64:
+ return Value;
+ }
+ HasError = true;
+ return 0;
}
- // SystemZ ELF
- uint64_t visitELF_390_32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- int64_t Res = Value + Addend;
-
- // Overflow check allows for both signed and unsigned interpretation.
- if (Res < INT32_MIN || Res > UINT32_MAX)
- HasError = true;
-
- return static_cast<uint32_t>(Res);
+ uint64_t visitMips64(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_MIPS_32:
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
+ case ELF::R_MIPS_64:
+ return Value + getELFAddend(R);
+ }
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_390_64(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R);
+ uint64_t visitPPC64(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_PPC64_ADDR32:
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
+ case ELF::R_PPC64_ADDR64:
+ return Value + getELFAddend(R);
+ }
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_SPARC_32(RelocationRef R, uint32_t Value) {
- return Value + getELFAddend(R);
+ uint64_t visitSystemz(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_390_32: {
+ int64_t Res = Value + getELFAddend(R);
+ if (Res < INT32_MIN || Res > UINT32_MAX)
+ HasError = true;
+ return static_cast<uint32_t>(Res);
+ }
+ case ELF::R_390_64:
+ return Value + getELFAddend(R);
+ }
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R);
+ uint64_t visitSparc64(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_SPARC_32:
+ case ELF::R_SPARC_64:
+ case ELF::R_SPARC_UA32:
+ case ELF::R_SPARC_UA64:
+ return Value + getELFAddend(R);
+ }
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) {
- return Value + getELFAddend(R);
+ uint64_t visitAmdgpu(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_AMDGPU_ABS32:
+ case ELF::R_AMDGPU_ABS64:
+ return Value + getELFAddend(R);
+ }
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) {
- int64_t Res = Value;
-
- // Overflow check allows for both signed and unsigned interpretation.
- if (Res < INT32_MIN || Res > UINT32_MAX)
- HasError = true;
-
- return static_cast<uint32_t>(Res);
+ uint64_t visitX86(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (Rel) {
+ case ELF::R_386_NONE:
+ return 0;
+ case ELF::R_386_32:
+ return Value;
+ case ELF::R_386_PC32:
+ return Value - R.getOffset();
+ }
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_HEX_32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return Value + Addend;
+ uint64_t visitPPC32(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (Rel == ELF::R_PPC_ADDR32)
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_AMDGPU_ABS32(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return Value + Addend;
+ uint64_t visitARM(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (Rel == ELF::R_ARM_ABS32) {
+ if ((int64_t)Value < INT32_MIN || (int64_t)Value > UINT32_MAX)
+ HasError = true;
+ return static_cast<uint32_t>(Value);
+ }
+ HasError = true;
+ return 0;
}
- uint64_t visitELF_AMDGPU_ABS64(RelocationRef R, uint64_t Value) {
- int64_t Addend = getELFAddend(R);
- return Value + Addend;
+ uint64_t visitLanai(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (Rel == ELF::R_LANAI_32)
+ return (Value + getELFAddend(R)) & 0xFFFFFFFF;
+ HasError = true;
+ return 0;
}
- /// I386 COFF
- uint64_t visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) {
- return static_cast<uint32_t>(Value);
+ uint64_t visitMips32(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (Rel == ELF::R_MIPS_32)
+ return Value & 0xFFFFFFFF;
+ HasError = true;
+ return 0;
}
- uint64_t visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) {
- return static_cast<uint32_t>(Value);
+ uint64_t visitSparc32(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (Rel == ELF::R_SPARC_32 || Rel == ELF::R_SPARC_UA32)
+ return Value + getELFAddend(R);
+ HasError = true;
+ return 0;
}
- /// AMD64 COFF
- uint64_t visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) {
- return static_cast<uint32_t>(Value);
+ uint64_t visitHexagon(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (Rel == ELF::R_HEX_32)
+ return Value + getELFAddend(R);
+ HasError = true;
+ return 0;
}
- uint64_t visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) {
- return Value;
+ uint64_t visitCOFF(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ switch (ObjToVisit.getArch()) {
+ case Triple::x86:
+ switch (Rel) {
+ case COFF::IMAGE_REL_I386_SECREL:
+ case COFF::IMAGE_REL_I386_DIR32:
+ return static_cast<uint32_t>(Value);
+ }
+ break;
+ case Triple::x86_64:
+ switch (Rel) {
+ case COFF::IMAGE_REL_AMD64_SECREL:
+ return static_cast<uint32_t>(Value);
+ case COFF::IMAGE_REL_AMD64_ADDR64:
+ return Value;
+ }
+ break;
+ }
+ HasError = true;
+ return 0;
}
- // X86_64 MachO
- uint64_t visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) {
- return Value;
+ uint64_t visitMachO(uint32_t Rel, RelocationRef R, uint64_t Value) {
+ if (ObjToVisit.getArch() == Triple::x86_64 &&
+ Rel == MachO::X86_64_RELOC_UNSIGNED)
+ return Value;
+ HasError = true;
+ return 0;
}
};
diff --git a/include/llvm/Object/Wasm.h b/include/llvm/Object/Wasm.h
index d200d4a148e3..de54a4928cce 100644
--- a/include/llvm/Object/Wasm.h
+++ b/include/llvm/Object/Wasm.h
@@ -119,6 +119,7 @@ public:
std::error_code getSectionName(DataRefImpl Sec,
StringRef &Res) const override;
uint64_t getSectionAddress(DataRefImpl Sec) const override;
+ uint64_t getSectionIndex(DataRefImpl Sec) const override;
uint64_t getSectionSize(DataRefImpl Sec) const override;
std::error_code getSectionContents(DataRefImpl Sec,
StringRef &Res) const override;
diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h
index 390e52774fea..8a323a255ca1 100644
--- a/include/llvm/Option/OptTable.h
+++ b/include/llvm/Option/OptTable.h
@@ -113,6 +113,14 @@ public:
return getInfo(id).MetaVar;
}
+ /// Find flags from OptTable which starts with Cur.
+ ///
+ /// \param [in] Cur - String prefix that all returned flags need
+ // to start with.
+ ///
+ /// \return The vector of flags which start with Cur.
+ std::vector<std::string> findByPrefix(StringRef Cur) const;
+
/// \brief Parse a single argument; returning the new argument and
/// updating Index.
///
diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h
index 1b07c33746e7..0dbb2cf9f269 100644
--- a/include/llvm/ProfileData/InstrProf.h
+++ b/include/llvm/ProfileData/InstrProf.h
@@ -212,12 +212,12 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
/// third field is the uncompressed strings; otherwise it is the
/// compressed string. When the string compression is off, the
/// second field will have value zero.
-Error collectPGOFuncNameStrings(const std::vector<std::string> &NameStrs,
+Error collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs,
bool doCompression, std::string &Result);
/// Produce \c Result string with the same format described above. The input
/// is vector of PGO function name variables that are referenced.
-Error collectPGOFuncNameStrings(const std::vector<GlobalVariable *> &NameVars,
+Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars,
std::string &Result, bool doCompression = true);
/// \c NameStrings is a string composed of one of more sub-strings encoded in
@@ -967,7 +967,7 @@ struct Header {
} // end namespace RawInstrProf
// Parse MemOP Size range option.
-void getMemOPSizeRangeFromOption(std::string Str, int64_t &RangeStart,
+void getMemOPSizeRangeFromOption(StringRef Str, int64_t &RangeStart,
int64_t &RangeLast);
} // end namespace llvm
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index fef5bf304566..d14a56cb87e0 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -671,7 +671,7 @@ public:
/// [AL, AH, CL] - Represent a list of defs
///
class ListInit final : public TypedInit, public FoldingSetNode,
- public TrailingObjects<BitsInit, Init *> {
+ public TrailingObjects<ListInit, Init *> {
unsigned NumValues;
public:
@@ -1137,17 +1137,19 @@ public:
/// to have at least one value then a (possibly empty) list of arguments. Each
/// argument can have a name associated with it.
///
-class DagInit : public TypedInit, public FoldingSetNode {
+class DagInit final : public TypedInit, public FoldingSetNode,
+ public TrailingObjects<DagInit, Init *, StringInit *> {
Init *Val;
StringInit *ValName;
- SmallVector<Init*, 4> Args;
- SmallVector<StringInit*, 4> ArgNames;
+ unsigned NumArgs;
+ unsigned NumArgNames;
- DagInit(Init *V, StringInit *VN, ArrayRef<Init *> ArgRange,
- ArrayRef<StringInit *> NameRange)
+ DagInit(Init *V, StringInit *VN, unsigned NumArgs, unsigned NumArgNames)
: TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN),
- Args(ArgRange.begin(), ArgRange.end()),
- ArgNames(NameRange.begin(), NameRange.end()) {}
+ NumArgs(NumArgs), NumArgNames(NumArgNames) {}
+
+ friend TrailingObjects;
+ size_t numTrailingObjects(OverloadToken<Init *>) const { return NumArgs; }
public:
DagInit(const DagInit &Other) = delete;
@@ -1173,20 +1175,24 @@ public:
return ValName ? ValName->getValue() : StringRef();
}
- unsigned getNumArgs() const { return Args.size(); }
+ unsigned getNumArgs() const { return NumArgs; }
Init *getArg(unsigned Num) const {
- assert(Num < Args.size() && "Arg number out of range!");
- return Args[Num];
+ assert(Num < NumArgs && "Arg number out of range!");
+ return getTrailingObjects<Init *>()[Num];
}
StringInit *getArgName(unsigned Num) const {
- assert(Num < ArgNames.size() && "Arg number out of range!");
- return ArgNames[Num];
+ 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();
}
+ ArrayRef<StringInit *> getArgNames() const {
+ return makeArrayRef(getTrailingObjects<StringInit *>(), NumArgNames);
+ }
+
Init *resolveReferences(Record &R, const RecordVal *RV) const override;
std::string getAsString() const override;
@@ -1194,20 +1200,20 @@ public:
typedef SmallVectorImpl<Init*>::const_iterator const_arg_iterator;
typedef SmallVectorImpl<StringInit*>::const_iterator const_name_iterator;
- inline const_arg_iterator arg_begin() const { return Args.begin(); }
- inline const_arg_iterator arg_end () const { return Args.end(); }
+ inline const_arg_iterator arg_begin() const { return getTrailingObjects<Init *>(); }
+ inline const_arg_iterator arg_end () const { return arg_begin() + NumArgs; }
inline iterator_range<const_arg_iterator> args() const {
return llvm::make_range(arg_begin(), arg_end());
}
- inline size_t arg_size () const { return Args.size(); }
- inline bool arg_empty() const { return Args.empty(); }
+ inline size_t arg_size () const { return NumArgs; }
+ inline bool arg_empty() const { return NumArgs == 0; }
- inline const_name_iterator name_begin() const { return ArgNames.begin(); }
- inline const_name_iterator name_end () const { return ArgNames.end(); }
+ inline const_name_iterator name_begin() const { return getTrailingObjects<StringInit *>(); }
+ inline const_name_iterator name_end () const { return name_begin() + NumArgNames; }
- inline size_t name_size () const { return ArgNames.size(); }
- inline bool name_empty() const { return ArgNames.empty(); }
+ inline size_t name_size () const { return NumArgNames; }
+ inline bool name_empty() const { return NumArgNames == 0; }
Init *getBit(unsigned Bit) const override {
llvm_unreachable("Illegal bit reference off dag");
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 1ca32d4c3589..17182b958ecb 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -405,7 +405,9 @@ public:
}
/// Returns if it's reasonable to merge stores to MemVT size.
- virtual bool canMergeStoresTo(EVT MemVT) const { return true; }
+ virtual bool canMergeStoresTo(unsigned AddressSpace, EVT MemVT) const {
+ return true;
+ }
/// \brief Return true if it is cheap to speculate a call to intrinsic cttz.
virtual bool isCheapToSpeculateCttz() const {
@@ -736,7 +738,7 @@ public:
if (VT.isExtended()) return Expand;
// If a target-specific SDNode requires legalization, require the target
// to provide custom legalization for it.
- if (Op > array_lengthof(OpActions[0])) return Custom;
+ if (Op >= array_lengthof(OpActions[0])) return Custom;
return OpActions[(unsigned)VT.getSimpleVT().SimpleTy][Op];
}
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index ba0a3ee1287a..856c288a071f 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -356,6 +356,13 @@ FunctionPass *createGVNHoistPass();
//===----------------------------------------------------------------------===//
//
+// GVNSink - This pass uses an "inverted" value numbering to decide the
+// similarity of expressions and sinks similar expressions into successors.
+//
+FunctionPass *createGVNSinkPass();
+
+//===----------------------------------------------------------------------===//
+//
// MergedLoadStoreMotion - This pass merges loads and stores in diamonds. Loads
// are hoisted into the header, while stores sink into the footer.
//
diff --git a/include/llvm/Transforms/Scalar/GVN.h b/include/llvm/Transforms/Scalar/GVN.h
index 8f05e8cdb233..3f97789cabbc 100644
--- a/include/llvm/Transforms/Scalar/GVN.h
+++ b/include/llvm/Transforms/Scalar/GVN.h
@@ -68,6 +68,24 @@ public:
class ValueTable {
DenseMap<Value *, uint32_t> valueNumbering;
DenseMap<Expression, uint32_t> expressionNumbering;
+
+ // Expressions is the vector of Expression. ExprIdx is the mapping from
+ // value number to the index of Expression in Expressions. We use it
+ // instead of a DenseMap because filling such mapping is faster than
+ // filling a DenseMap and the compile time is a little better.
+ uint32_t nextExprNumber;
+ std::vector<Expression> Expressions;
+ std::vector<uint32_t> ExprIdx;
+ // Value number to PHINode mapping. Used for phi-translate in scalarpre.
+ DenseMap<uint32_t, PHINode *> NumberingPhi;
+ // Cache for phi-translate in scalarpre.
+ typedef DenseMap<std::pair<uint32_t, const BasicBlock *>, uint32_t>
+ PhiTranslateMap;
+ PhiTranslateMap PhiTranslateTable;
+ // Map the block to reversed postorder traversal number. It is used to
+ // find back edge easily.
+ DenseMap<const BasicBlock *, uint32_t> BlockRPONumber;
+
AliasAnalysis *AA;
MemoryDependenceResults *MD;
DominatorTree *DT;
@@ -79,6 +97,10 @@ public:
Value *LHS, Value *RHS);
Expression createExtractvalueExpr(ExtractValueInst *EI);
uint32_t lookupOrAddCall(CallInst *C);
+ uint32_t phiTranslateImpl(const BasicBlock *BB, const BasicBlock *PhiBlock,
+ uint32_t Num, GVN &Gvn);
+ std::pair<uint32_t, bool> assignExpNewValueNum(Expression &exp);
+ bool areAllValsInBB(uint32_t num, const BasicBlock *BB, GVN &Gvn);
public:
ValueTable();
@@ -87,9 +109,12 @@ public:
~ValueTable();
uint32_t lookupOrAdd(Value *V);
- uint32_t lookup(Value *V) const;
+ uint32_t lookup(Value *V, bool Verify = true) const;
uint32_t lookupOrAddCmp(unsigned Opcode, CmpInst::Predicate Pred,
Value *LHS, Value *RHS);
+ uint32_t phiTranslate(const BasicBlock *BB, const BasicBlock *PhiBlock,
+ uint32_t Num, GVN &Gvn);
+ void assignBlockRPONumber(Function &F);
bool exists(Value *V) const;
void add(Value *V, uint32_t num);
void clear();
@@ -238,7 +263,12 @@ struct GVNHoistPass : PassInfoMixin<GVNHoistPass> {
/// \brief Run the pass over the function.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
-
+/// \brief Uses an "inverted" value numbering to decide the similarity of
+/// expressions and sinks similar expressions into successors.
+struct GVNSinkPass : PassInfoMixin<GVNSinkPass> {
+ /// \brief Run the pass over the function.
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
}
#endif
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index b5a5f4c2704c..8942111307ff 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -356,6 +356,10 @@ void combineMetadata(Instruction *K, const Instruction *J, ArrayRef<unsigned> Kn
/// Unknown metadata is removed.
void combineMetadataForCSE(Instruction *K, const Instruction *J);
+// Replace each use of 'From' with 'To', if that use does not belong to basic
+// block where 'From' is defined. Returns the number of replacements made.
+unsigned replaceNonLocalUsesWith(Instruction *From, Value *To);
+
/// Replace each use of 'From' with 'To' if that use is dominated by
/// the given edge. Returns the number of replacements made.
unsigned replaceDominatedUsesWith(Value *From, Value *To, DominatorTree &DT,
@@ -406,6 +410,14 @@ bool recognizeBSwapOrBitReverseIdiom(
void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI,
const TargetLibraryInfo *TLI);
+//===----------------------------------------------------------------------===//
+// Transform predicates
+//
+
+/// Given an instruction, is it legal to set operand OpIdx to a non-constant
+/// value?
+bool canReplaceOperandWithVariable(const Instruction *I, unsigned OpIdx);
+
} // End llvm namespace
#endif
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index 0ca712bbfe70..79517ec6a3a8 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -687,11 +687,8 @@ Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0, Constant *Op1,
// bits.
if (Opc == Instruction::And) {
- unsigned BitWidth = DL.getTypeSizeInBits(Op0->getType()->getScalarType());
- KnownBits Known0(BitWidth);
- KnownBits Known1(BitWidth);
- computeKnownBits(Op0, Known0, DL);
- computeKnownBits(Op1, Known1, DL);
+ KnownBits Known0 = computeKnownBits(Op0, DL);
+ KnownBits Known1 = computeKnownBits(Op1, DL);
if ((Known1.One | Known0.Zero).isAllOnesValue()) {
// All the bits of Op0 that the 'and' could be masking are already zero.
return Op0;
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index 2e72d5aa8269..122442bafb11 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/lib/Analysis/InstructionSimplify.cpp
@@ -688,9 +688,7 @@ static Value *SimplifySubInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
if (isNUW)
return Op0;
- unsigned BitWidth = Op1->getType()->getScalarSizeInBits();
- KnownBits Known(BitWidth);
- computeKnownBits(Op1, Known, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
+ KnownBits Known = computeKnownBits(Op1, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
if (Known.Zero.isMaxSignedValue()) {
// Op1 is either 0 or the minimum signed value. If the sub is NSW, then
// Op1 must be 0 because negating the minimum signed value is undefined.
@@ -1309,15 +1307,13 @@ static Value *SimplifyShift(Instruction::BinaryOps Opcode, Value *Op0,
// If any bits in the shift amount make that value greater than or equal to
// the number of bits in the type, the shift is undefined.
- unsigned BitWidth = Op1->getType()->getScalarSizeInBits();
- KnownBits Known(BitWidth);
- computeKnownBits(Op1, Known, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
- if (Known.One.getLimitedValue() >= BitWidth)
+ KnownBits Known = computeKnownBits(Op1, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
+ if (Known.One.getLimitedValue() >= Known.getBitWidth())
return UndefValue::get(Op0->getType());
// If all valid bits in the shift amount are known zero, the first operand is
// unchanged.
- unsigned NumValidShiftBits = Log2_32_Ceil(BitWidth);
+ unsigned NumValidShiftBits = Log2_32_Ceil(Known.getBitWidth());
if (Known.countMinTrailingZeros() >= NumValidShiftBits)
return Op0;
@@ -1343,9 +1339,7 @@ static Value *SimplifyRightShift(Instruction::BinaryOps Opcode, Value *Op0,
// The low bit cannot be shifted out of an exact shift if it is set.
if (isExact) {
- unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
- KnownBits Op0Known(BitWidth);
- computeKnownBits(Op0, Op0Known, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT);
+ KnownBits Op0Known = computeKnownBits(Op0, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT);
if (Op0Known.One[0])
return Op0;
}
@@ -1428,6 +1422,8 @@ Value *llvm::SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
return ::SimplifyAShrInst(Op0, Op1, isExact, Q, RecursionLimit);
}
+/// Commuted variants are assumed to be handled by calling this function again
+/// with the parameters swapped.
static Value *simplifyUnsignedRangeCheck(ICmpInst *ZeroICmp,
ICmpInst *UnsignedICmp, bool IsAnd) {
Value *X, *Y;
@@ -1560,20 +1556,8 @@ static Value *simplifyAndOrOfICmpsWithConstants(ICmpInst *Cmp0, ICmpInst *Cmp1,
return nullptr;
}
-/// Commuted variants are assumed to be handled by calling this function again
-/// with the parameters swapped.
-static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
- if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/true))
- return X;
-
- if (Value *X = simplifyAndOfICmpsWithSameOperands(Op0, Op1))
- return X;
-
- if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, true))
- return X;
-
+static Value *simplifyAndOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1) {
// (icmp (add V, C0), C1) & (icmp V, C0)
- Type *ITy = Op0->getType();
ICmpInst::Predicate Pred0, Pred1;
const APInt *C0, *C1;
Value *V;
@@ -1587,6 +1571,7 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
if (AddInst->getOperand(1) != Op1->getOperand(1))
return nullptr;
+ Type *ITy = Op0->getType();
bool isNSW = AddInst->hasNoSignedWrap();
bool isNUW = AddInst->hasNoUnsignedWrap();
@@ -1617,18 +1602,29 @@ static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
return nullptr;
}
-/// Commuted variants are assumed to be handled by calling this function again
-/// with the parameters swapped.
-static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
- if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/false))
+static Value *simplifyAndOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
+ if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/true))
+ return X;
+ if (Value *X = simplifyUnsignedRangeCheck(Op1, Op0, /*IsAnd=*/true))
return X;
- if (Value *X = simplifyOrOfICmpsWithSameOperands(Op0, Op1))
+ if (Value *X = simplifyAndOfICmpsWithSameOperands(Op0, Op1))
+ return X;
+ if (Value *X = simplifyAndOfICmpsWithSameOperands(Op1, Op0))
return X;
- if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, false))
+ if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, true))
+ return X;
+
+ if (Value *X = simplifyAndOfICmpsWithAdd(Op0, Op1))
+ return X;
+ if (Value *X = simplifyAndOfICmpsWithAdd(Op1, Op0))
return X;
+ return nullptr;
+}
+
+static Value *simplifyOrOfICmpsWithAdd(ICmpInst *Op0, ICmpInst *Op1) {
// (icmp (add V, C0), C1) | (icmp V, C0)
ICmpInst::Predicate Pred0, Pred1;
const APInt *C0, *C1;
@@ -1674,19 +1670,24 @@ static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
return nullptr;
}
-static Value *simplifyPossiblyCastedAndOrOfICmps(ICmpInst *Cmp0, ICmpInst *Cmp1,
- bool IsAnd, CastInst *Cast) {
- Value *V =
- IsAnd ? simplifyAndOfICmps(Cmp0, Cmp1) : simplifyOrOfICmps(Cmp0, Cmp1);
- if (!V)
- return nullptr;
- if (!Cast)
- return V;
+static Value *simplifyOrOfICmps(ICmpInst *Op0, ICmpInst *Op1) {
+ if (Value *X = simplifyUnsignedRangeCheck(Op0, Op1, /*IsAnd=*/false))
+ return X;
+ if (Value *X = simplifyUnsignedRangeCheck(Op1, Op0, /*IsAnd=*/false))
+ return X;
- // If we looked through casts, we can only handle a constant simplification
- // because we are not allowed to create a cast instruction here.
- if (auto *C = dyn_cast<Constant>(V))
- return ConstantExpr::getCast(Cast->getOpcode(), C, Cast->getType());
+ if (Value *X = simplifyOrOfICmpsWithSameOperands(Op0, Op1))
+ return X;
+ if (Value *X = simplifyOrOfICmpsWithSameOperands(Op1, Op0))
+ return X;
+
+ if (Value *X = simplifyAndOrOfICmpsWithConstants(Op0, Op1, false))
+ return X;
+
+ if (Value *X = simplifyOrOfICmpsWithAdd(Op0, Op1))
+ return X;
+ if (Value *X = simplifyOrOfICmpsWithAdd(Op1, Op0))
+ return X;
return nullptr;
}
@@ -1706,11 +1707,18 @@ static Value *simplifyAndOrOfICmps(Value *Op0, Value *Op1, bool IsAnd) {
if (!Cmp0 || !Cmp1)
return nullptr;
- if (Value *V = simplifyPossiblyCastedAndOrOfICmps(Cmp0, Cmp1, IsAnd, Cast0))
- return V;
- if (Value *V = simplifyPossiblyCastedAndOrOfICmps(Cmp1, Cmp0, IsAnd, Cast0))
+ Value *V =
+ IsAnd ? simplifyAndOfICmps(Cmp0, Cmp1) : simplifyOrOfICmps(Cmp0, Cmp1);
+ if (!V)
+ return nullptr;
+ if (!Cast0)
return V;
+ // If we looked through casts, we can only handle a constant simplification
+ // because we are not allowed to create a cast instruction here.
+ if (auto *C = dyn_cast<Constant>(V))
+ return ConstantExpr::getCast(Cast0->getOpcode(), C, Cast0->getType());
+
return nullptr;
}
@@ -1927,37 +1935,27 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
MaxRecurse))
return V;
- // (A & C)|(B & D)
- Value *C = nullptr, *D = nullptr;
- if (match(Op0, m_And(m_Value(A), m_Value(C))) &&
- match(Op1, m_And(m_Value(B), m_Value(D)))) {
- ConstantInt *C1 = dyn_cast<ConstantInt>(C);
- ConstantInt *C2 = dyn_cast<ConstantInt>(D);
- if (C1 && C2 && (C1->getValue() == ~C2->getValue())) {
+ // (A & C1)|(B & C2)
+ const APInt *C1, *C2;
+ if (match(Op0, m_And(m_Value(A), m_APInt(C1))) &&
+ match(Op1, m_And(m_Value(B), m_APInt(C2)))) {
+ if (*C1 == ~*C2) {
// (A & C1)|(B & C2)
// If we have: ((V + N) & C1) | (V & C2)
// .. and C2 = ~C1 and C2 is 0+1+ and (N & C2) == 0
// replace with V+N.
- Value *V1, *V2;
- if ((C2->getValue() & (C2->getValue() + 1)) == 0 && // C2 == 0+1+
- match(A, m_Add(m_Value(V1), m_Value(V2)))) {
+ Value *N;
+ if (C2->isMask() && // C2 == 0+1+
+ match(A, m_c_Add(m_Specific(B), m_Value(N)))) {
// Add commutes, try both ways.
- if (V1 == B &&
- MaskedValueIsZero(V2, C2->getValue(), Q.DL, 0, Q.AC, Q.CxtI, Q.DT))
- return A;
- if (V2 == B &&
- MaskedValueIsZero(V1, C2->getValue(), Q.DL, 0, Q.AC, Q.CxtI, Q.DT))
+ if (MaskedValueIsZero(N, *C2, Q.DL, 0, Q.AC, Q.CxtI, Q.DT))
return A;
}
// Or commutes, try both ways.
- if ((C1->getValue() & (C1->getValue() + 1)) == 0 &&
- match(B, m_Add(m_Value(V1), m_Value(V2)))) {
+ if (C1->isMask() &&
+ match(B, m_c_Add(m_Specific(A), m_Value(N)))) {
// Add commutes, try both ways.
- if (V1 == A &&
- MaskedValueIsZero(V2, C1->getValue(), Q.DL, 0, Q.AC, Q.CxtI, Q.DT))
- return B;
- if (V2 == A &&
- MaskedValueIsZero(V1, C1->getValue(), Q.DL, 0, Q.AC, Q.CxtI, Q.DT))
+ if (MaskedValueIsZero(N, *C1, Q.DL, 0, Q.AC, Q.CxtI, Q.DT))
return B;
}
}
@@ -3372,9 +3370,7 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
if (ICmpInst::isEquality(Pred)) {
const APInt *RHSVal;
if (match(RHS, m_APInt(RHSVal))) {
- unsigned BitWidth = RHSVal->getBitWidth();
- KnownBits LHSKnown(BitWidth);
- computeKnownBits(LHS, LHSKnown, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT);
+ KnownBits LHSKnown = computeKnownBits(LHS, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT);
if (LHSKnown.Zero.intersects(*RHSVal) ||
!LHSKnown.One.isSubsetOf(*RHSVal))
return Pred == ICmpInst::ICMP_EQ ? ConstantInt::getFalse(ITy)
@@ -3539,6 +3535,10 @@ static const Value *SimplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
if (V == Op)
return RepOp;
+ // We cannot replace a constant, and shouldn't even try.
+ if (isa<Constant>(Op))
+ return nullptr;
+
auto *I = dyn_cast<Instruction>(V);
if (!I)
return nullptr;
@@ -4444,19 +4444,21 @@ static Value *SimplifyIntrinsic(Function *F, IterTy ArgBegin, IterTy ArgEnd,
case Intrinsic::uadd_with_overflow:
case Intrinsic::sadd_with_overflow: {
// X + undef -> undef
- if (isa<UndefValue>(RHS))
+ if (isa<UndefValue>(LHS) || isa<UndefValue>(RHS))
return UndefValue::get(ReturnType);
return nullptr;
}
case Intrinsic::umul_with_overflow:
case Intrinsic::smul_with_overflow: {
+ // 0 * X -> { 0, false }
// X * 0 -> { 0, false }
- if (match(RHS, m_Zero()))
+ if (match(LHS, m_Zero()) || match(RHS, m_Zero()))
return Constant::getNullValue(ReturnType);
+ // undef * X -> { 0, false }
// X * undef -> { 0, false }
- if (match(RHS, m_Undef()))
+ if (match(LHS, m_Undef()) || match(RHS, m_Undef()))
return Constant::getNullValue(ReturnType);
return nullptr;
@@ -4680,9 +4682,7 @@ Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ,
// In general, it is possible for computeKnownBits to determine all bits in a
// value even when the operands are not all constants.
if (!Result && I->getType()->isIntOrIntVectorTy()) {
- unsigned BitWidth = I->getType()->getScalarSizeInBits();
- KnownBits Known(BitWidth);
- computeKnownBits(I, Known, Q.DL, /*Depth*/ 0, Q.AC, I, Q.DT, ORE);
+ KnownBits Known = computeKnownBits(I, Q.DL, /*Depth*/ 0, Q.AC, I, Q.DT, ORE);
if (Known.isConstant())
Result = ConstantInt::get(I->getType(), Known.getConstant());
}
diff --git a/lib/Analysis/Lint.cpp b/lib/Analysis/Lint.cpp
index 471ccb62970d..e6391792bc23 100644
--- a/lib/Analysis/Lint.cpp
+++ b/lib/Analysis/Lint.cpp
@@ -534,9 +534,7 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
VectorType *VecTy = dyn_cast<VectorType>(V->getType());
if (!VecTy) {
- unsigned BitWidth = V->getType()->getIntegerBitWidth();
- KnownBits Known(BitWidth);
- computeKnownBits(V, Known, DL, 0, AC, dyn_cast<Instruction>(V), DT);
+ KnownBits Known = computeKnownBits(V, DL, 0, AC, dyn_cast<Instruction>(V), DT);
return Known.isZero();
}
@@ -550,14 +548,12 @@ static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT,
// For a vector, KnownZero will only be true if all values are zero, so check
// this per component
- unsigned BitWidth = VecTy->getElementType()->getIntegerBitWidth();
for (unsigned I = 0, N = VecTy->getNumElements(); I != N; ++I) {
Constant *Elem = C->getAggregateElement(I);
if (isa<UndefValue>(Elem))
return true;
- KnownBits Known(BitWidth);
- computeKnownBits(Elem, Known, DL);
+ KnownBits Known = computeKnownBits(Elem, DL);
if (Known.isZero())
return true;
}
diff --git a/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp
index 0b5f6266e373..e988f6444a58 100644
--- a/lib/Analysis/LoopPass.cpp
+++ b/lib/Analysis/LoopPass.cpp
@@ -73,30 +73,23 @@ LPPassManager::LPPassManager()
CurrentLoop = nullptr;
}
-// Inset loop into loop nest (LoopInfo) and loop queue (LQ).
-Loop &LPPassManager::addLoop(Loop *ParentLoop) {
- // Create a new loop. LI will take ownership.
- Loop *L = new Loop();
-
- // Insert into the loop nest and the loop queue.
- if (!ParentLoop) {
+// Insert loop into loop nest (LoopInfo) and loop queue (LQ).
+void LPPassManager::addLoop(Loop &L) {
+ if (!L.getParentLoop()) {
// This is the top level loop.
- LI->addTopLevelLoop(L);
- LQ.push_front(L);
- return *L;
+ LQ.push_front(&L);
+ return;
}
- ParentLoop->addChildLoop(L);
// Insert L into the loop queue after the parent loop.
for (auto I = LQ.begin(), E = LQ.end(); I != E; ++I) {
- if (*I == L->getParentLoop()) {
+ if (*I == L.getParentLoop()) {
// deque does not support insert after.
++I;
- LQ.insert(I, 1, L);
- break;
+ LQ.insert(I, 1, &L);
+ return;
}
}
- return *L;
}
/// cloneBasicBlockSimpleAnalysis - Invoke cloneBasicBlockAnalysis hook for
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index 78ded8141c08..d280fda0a162 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -2178,6 +2178,63 @@ StrengthenNoWrapFlags(ScalarEvolution *SE, SCEVTypes Type,
return Flags;
}
+bool ScalarEvolution::isAvailableAtLoopEntry(const SCEV *S, const Loop *L,
+ DominatorTree &DT, LoopInfo &LI) {
+ if (!isLoopInvariant(S, L))
+ return false;
+ // If a value depends on a SCEVUnknown which is defined after the loop, we
+ // conservatively assume that we cannot calculate it at the loop's entry.
+ struct FindDominatedSCEVUnknown {
+ bool Found = false;
+ const Loop *L;
+ DominatorTree &DT;
+ LoopInfo &LI;
+
+ FindDominatedSCEVUnknown(const Loop *L, DominatorTree &DT, LoopInfo &LI)
+ : L(L), DT(DT), LI(LI) {}
+
+ bool checkSCEVUnknown(const SCEVUnknown *SU) {
+ if (auto *I = dyn_cast<Instruction>(SU->getValue())) {
+ if (DT.dominates(L->getHeader(), I->getParent()))
+ Found = true;
+ else
+ assert(DT.dominates(I->getParent(), L->getHeader()) &&
+ "No dominance relationship between SCEV and loop?");
+ }
+ return false;
+ }
+
+ bool follow(const SCEV *S) {
+ switch (static_cast<SCEVTypes>(S->getSCEVType())) {
+ case scConstant:
+ return false;
+ case scAddRecExpr:
+ case scTruncate:
+ case scZeroExtend:
+ case scSignExtend:
+ case scAddExpr:
+ case scMulExpr:
+ case scUMaxExpr:
+ case scSMaxExpr:
+ case scUDivExpr:
+ return true;
+ case scUnknown:
+ return checkSCEVUnknown(cast<SCEVUnknown>(S));
+ case scCouldNotCompute:
+ llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
+ }
+ return false;
+ }
+
+ bool isDone() { return Found; }
+ };
+
+ FindDominatedSCEVUnknown FSU(L, DT, LI);
+ SCEVTraversal<FindDominatedSCEVUnknown> ST(FSU);
+ ST.visitAll(S);
+ return !FSU.Found;
+}
+
/// Get a canonical add expression, or something simpler if possible.
const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags,
@@ -2459,7 +2516,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
const Loop *AddRecLoop = AddRec->getLoop();
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
- if (isLoopInvariant(Ops[i], AddRecLoop)) {
+ if (isAvailableAtLoopEntry(Ops[i], AddRecLoop, DT, LI)) {
LIOps.push_back(Ops[i]);
Ops.erase(Ops.begin()+i);
--i; --e;
@@ -2734,7 +2791,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
const Loop *AddRecLoop = AddRec->getLoop();
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
- if (isLoopInvariant(Ops[i], AddRecLoop)) {
+ if (isAvailableAtLoopEntry(Ops[i], AddRecLoop, DT, LI)) {
LIOps.push_back(Ops[i]);
Ops.erase(Ops.begin()+i);
--i; --e;
@@ -4648,10 +4705,7 @@ uint32_t ScalarEvolution::GetMinTrailingZerosImpl(const SCEV *S) {
if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
// For a SCEVUnknown, ask ValueTracking.
- unsigned BitWidth = getTypeSizeInBits(U->getType());
- KnownBits Known(BitWidth);
- computeKnownBits(U->getValue(), Known, getDataLayout(), 0, &AC,
- nullptr, &DT);
+ KnownBits Known = computeKnownBits(U->getValue(), getDataLayout(), 0, &AC, nullptr, &DT);
return Known.countMinTrailingZeros();
}
@@ -4831,8 +4885,7 @@ ScalarEvolution::getRange(const SCEV *S,
const DataLayout &DL = getDataLayout();
if (SignHint == ScalarEvolution::HINT_RANGE_UNSIGNED) {
// For a SCEVUnknown, ask ValueTracking.
- KnownBits Known(BitWidth);
- computeKnownBits(U->getValue(), Known, DL, 0, &AC, nullptr, &DT);
+ KnownBits Known = computeKnownBits(U->getValue(), DL, 0, &AC, nullptr, &DT);
if (Known.One != ~Known.Zero + 1)
ConservativeResult =
ConservativeResult.intersectWith(ConstantRange(Known.One,
@@ -9537,8 +9590,11 @@ struct SCEVCollectAddRecMultiplies {
bool HasAddRec = false;
SmallVector<const SCEV *, 0> Operands;
for (auto Op : Mul->operands()) {
- if (isa<SCEVUnknown>(Op)) {
+ const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op);
+ if (Unknown && !isa<CallInst>(Unknown->getValue())) {
Operands.push_back(Op);
+ } else if (Unknown) {
+ HasAddRec = true;
} else {
bool ContainsAddRec;
SCEVHasAddRec ContiansAddRec(ContainsAddRec);
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index 86cbd79aa84e..f9b9df2bc707 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -1305,12 +1305,17 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) {
// Expand the core addrec. If we need post-loop scaling, force it to
// expand to an integer type to avoid the need for additional casting.
Type *ExpandTy = PostLoopScale ? IntTy : STy;
+ // We can't use a pointer type for the addrec if the pointer type is
+ // non-integral.
+ Type *AddRecPHIExpandTy =
+ DL.isNonIntegralPointerType(STy) ? Normalized->getType() : ExpandTy;
+
// In some cases, we decide to reuse an existing phi node but need to truncate
// it and/or invert the step.
Type *TruncTy = nullptr;
bool InvertStep = false;
- PHINode *PN = getAddRecExprPHILiterally(Normalized, L, ExpandTy, IntTy,
- TruncTy, InvertStep);
+ PHINode *PN = getAddRecExprPHILiterally(Normalized, L, AddRecPHIExpandTy,
+ IntTy, TruncTy, InvertStep);
// Accommodate post-inc mode, if necessary.
Value *Result;
@@ -1383,8 +1388,15 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) {
// Re-apply any non-loop-dominating offset.
if (PostLoopOffset) {
if (PointerType *PTy = dyn_cast<PointerType>(ExpandTy)) {
- const SCEV *const OffsetArray[1] = { PostLoopOffset };
- Result = expandAddToGEP(OffsetArray, OffsetArray+1, PTy, IntTy, Result);
+ if (Result->getType()->isIntegerTy()) {
+ Value *Base = expandCodeFor(PostLoopOffset, ExpandTy);
+ const SCEV *const OffsetArray[1] = {SE.getUnknown(Result)};
+ Result = expandAddToGEP(OffsetArray, OffsetArray + 1, PTy, IntTy, Base);
+ } else {
+ const SCEV *const OffsetArray[1] = {PostLoopOffset};
+ Result =
+ expandAddToGEP(OffsetArray, OffsetArray + 1, PTy, IntTy, Result);
+ }
} else {
Result = InsertNoopCastOfTo(Result, IntTy);
Result = Builder.CreateAdd(Result,
diff --git a/lib/Analysis/TargetTransformInfo.cpp b/lib/Analysis/TargetTransformInfo.cpp
index 8a5d10473662..7a8d4f3be24f 100644
--- a/lib/Analysis/TargetTransformInfo.cpp
+++ b/lib/Analysis/TargetTransformInfo.cpp
@@ -149,6 +149,10 @@ bool TargetTransformInfo::isLegalMaskedScatter(Type *DataType) const {
return TTIImpl->isLegalMaskedGather(DataType);
}
+bool TargetTransformInfo::prefersVectorizedAddressing() const {
+ return TTIImpl->prefersVectorizedAddressing();
+}
+
int TargetTransformInfo::getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset,
bool HasBaseReg,
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 8e6c1096eec8..bd79cd56a18b 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -149,8 +149,10 @@ static KnownBits computeKnownBits(const Value *V, unsigned Depth,
KnownBits llvm::computeKnownBits(const Value *V, const DataLayout &DL,
unsigned Depth, AssumptionCache *AC,
const Instruction *CxtI,
- const DominatorTree *DT) {
- return ::computeKnownBits(V, Depth, Query(DL, AC, safeCxtI(V, CxtI), DT));
+ const DominatorTree *DT,
+ OptimizationRemarkEmitter *ORE) {
+ return ::computeKnownBits(V, Depth,
+ Query(DL, AC, safeCxtI(V, CxtI), DT, ORE));
}
bool llvm::haveNoCommonBitsSet(const Value *LHS, const Value *RHS,
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index 1f8b50342c2d..c1d81ac203a1 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -660,10 +660,12 @@ void ModuleBitcodeWriter::writeAttributeTable() {
SmallVector<uint64_t, 64> Record;
for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
- const AttributeList &A = Attrs[i];
- for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i)
- Record.push_back(
- VE.getAttributeGroupID({A.getSlotIndex(i), A.getSlotAttributes(i)}));
+ AttributeList AL = Attrs[i];
+ for (unsigned i = AL.index_begin(), e = AL.index_end(); i != e; ++i) {
+ AttributeSet AS = AL.getAttributes(i);
+ if (AS.hasAttributes())
+ Record.push_back(VE.getAttributeGroupID({i, AS}));
+ }
Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
Record.clear();
@@ -3413,30 +3415,8 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
// Create value IDs for undefined references.
forEachSummary([&](GVInfo I) {
- if (auto *VS = dyn_cast<GlobalVarSummary>(I.second)) {
- for (auto &RI : VS->refs())
- assignValueId(RI.getGUID());
- return;
- }
-
- auto *FS = dyn_cast<FunctionSummary>(I.second);
- if (!FS)
- return;
- for (auto &RI : FS->refs())
+ for (auto &RI : I.second->refs())
assignValueId(RI.getGUID());
-
- for (auto &EI : FS->calls()) {
- GlobalValue::GUID GUID = EI.first.getGUID();
- if (!hasValueId(GUID)) {
- // For SamplePGO, the indirect call targets for local functions will
- // have its original name annotated in profile. We try to find the
- // corresponding PGOFuncName as the GUID.
- GUID = Index.getGUIDFromOriginalID(GUID);
- if (GUID == 0 || !hasValueId(GUID))
- continue;
- }
- assignValueId(GUID);
- }
});
for (const auto &GVI : valueIds()) {
diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp
index fd76400331d9..bb626baabd12 100644
--- a/lib/Bitcode/Writer/ValueEnumerator.cpp
+++ b/lib/Bitcode/Writer/ValueEnumerator.cpp
@@ -902,8 +902,11 @@ void ValueEnumerator::EnumerateAttributes(AttributeList PAL) {
}
// Do lookups for all attribute groups.
- for (unsigned i = 0, e = PAL.getNumSlots(); i != e; ++i) {
- IndexAndAttrSet Pair = {PAL.getSlotIndex(i), PAL.getSlotAttributes(i)};
+ for (unsigned i = PAL.index_begin(), e = PAL.index_end(); i != e; ++i) {
+ AttributeSet AS = PAL.getAttributes(i);
+ if (!AS.hasAttributes())
+ continue;
+ IndexAndAttrSet Pair = {i, AS};
unsigned &Entry = AttributeGroupMap[Pair];
if (Entry == 0) {
AttributeGroups.push_back(Pair);
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 7ddb86d80bf0..d72cf5922987 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -628,12 +628,15 @@ void AsmPrinter::EmitDebugThreadLocal(const MCExpr *Value,
/// EmitFunctionHeader - This method emits the header for the current
/// function.
void AsmPrinter::EmitFunctionHeader() {
+ const Function *F = MF->getFunction();
+
+ if (isVerbose())
+ OutStreamer->GetCommentOS() << "-- Begin function " << F->getName() << '\n';
+
// Print out constants referenced by the function
EmitConstantPool();
// Print the 'header' of function.
- const Function *F = MF->getFunction();
-
OutStreamer->SwitchSection(getObjFileLowering().SectionForGlobal(F, TM));
EmitVisibility(CurrentFnSym, F->getVisibility());
@@ -1107,6 +1110,9 @@ void AsmPrinter::EmitFunctionBody() {
HI.Handler->endFunction(MF);
}
+ if (isVerbose())
+ OutStreamer->GetCommentOS() << "-- End function\n";
+
OutStreamer->AddBlankLine();
}
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 1b39e46ee466..114aea391a86 100644
--- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -1025,11 +1025,11 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
bool EmptyPrologue = true;
for (const auto &MBB : *MF) {
for (const auto &MI : MBB) {
- if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
+ if (!MI.isMetaInstruction() && !MI.getFlag(MachineInstr::FrameSetup) &&
MI.getDebugLoc()) {
PrologEndLoc = MI.getDebugLoc();
break;
- } else if (!MI.isDebugValue()) {
+ } else if (!MI.isMetaInstruction()) {
EmptyPrologue = false;
}
}
@@ -1562,7 +1562,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
EnumeratorCount++;
}
}
- FTI = FLRB.end();
+ FTI = FLRB.end(true);
}
std::string FullName = getFullyQualifiedName(Ty);
@@ -1869,7 +1869,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
MemberCount++;
}
- TypeIndex FieldTI = FLBR.end();
+ TypeIndex FieldTI = FLBR.end(true);
return std::make_tuple(FieldTI, Info.VShapeTI, MemberCount,
!Info.NestedClasses.empty());
}
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.cpp b/lib/CodeGen/AsmPrinter/DIEHash.cpp
index 8e3b88d0af0e..201030f0ac5c 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.cpp
+++ b/lib/CodeGen/AsmPrinter/DIEHash.cpp
@@ -116,65 +116,17 @@ void DIEHash::addParentContext(const DIE &Parent) {
// Collect all of the attributes for a particular DIE in single structure.
void DIEHash::collectAttributes(const DIE &Die, DIEAttrs &Attrs) {
-#define COLLECT_ATTR(NAME) \
- case dwarf::NAME: \
- Attrs.NAME = V; \
- break
for (const auto &V : Die.values()) {
DEBUG(dbgs() << "Attribute: "
<< dwarf::AttributeString(V.getAttribute())
<< " added.\n");
switch (V.getAttribute()) {
- COLLECT_ATTR(DW_AT_name);
- COLLECT_ATTR(DW_AT_accessibility);
- COLLECT_ATTR(DW_AT_address_class);
- COLLECT_ATTR(DW_AT_allocated);
- COLLECT_ATTR(DW_AT_artificial);
- COLLECT_ATTR(DW_AT_associated);
- COLLECT_ATTR(DW_AT_binary_scale);
- COLLECT_ATTR(DW_AT_bit_offset);
- COLLECT_ATTR(DW_AT_bit_size);
- COLLECT_ATTR(DW_AT_bit_stride);
- COLLECT_ATTR(DW_AT_byte_size);
- COLLECT_ATTR(DW_AT_byte_stride);
- COLLECT_ATTR(DW_AT_const_expr);
- COLLECT_ATTR(DW_AT_const_value);
- COLLECT_ATTR(DW_AT_containing_type);
- COLLECT_ATTR(DW_AT_count);
- COLLECT_ATTR(DW_AT_data_bit_offset);
- COLLECT_ATTR(DW_AT_data_location);
- COLLECT_ATTR(DW_AT_data_member_location);
- COLLECT_ATTR(DW_AT_decimal_scale);
- COLLECT_ATTR(DW_AT_decimal_sign);
- COLLECT_ATTR(DW_AT_default_value);
- COLLECT_ATTR(DW_AT_digit_count);
- COLLECT_ATTR(DW_AT_discr);
- COLLECT_ATTR(DW_AT_discr_list);
- COLLECT_ATTR(DW_AT_discr_value);
- COLLECT_ATTR(DW_AT_encoding);
- COLLECT_ATTR(DW_AT_enum_class);
- COLLECT_ATTR(DW_AT_endianity);
- COLLECT_ATTR(DW_AT_explicit);
- COLLECT_ATTR(DW_AT_is_optional);
- COLLECT_ATTR(DW_AT_location);
- COLLECT_ATTR(DW_AT_lower_bound);
- COLLECT_ATTR(DW_AT_mutable);
- COLLECT_ATTR(DW_AT_ordering);
- COLLECT_ATTR(DW_AT_picture_string);
- COLLECT_ATTR(DW_AT_prototyped);
- COLLECT_ATTR(DW_AT_small);
- COLLECT_ATTR(DW_AT_segment);
- COLLECT_ATTR(DW_AT_string_length);
- COLLECT_ATTR(DW_AT_threads_scaled);
- COLLECT_ATTR(DW_AT_upper_bound);
- COLLECT_ATTR(DW_AT_use_location);
- COLLECT_ATTR(DW_AT_use_UTF8);
- COLLECT_ATTR(DW_AT_variable_parameter);
- COLLECT_ATTR(DW_AT_virtuality);
- COLLECT_ATTR(DW_AT_visibility);
- COLLECT_ATTR(DW_AT_vtable_elem_location);
- COLLECT_ATTR(DW_AT_type);
+#define HANDLE_DIE_HASH_ATTR(NAME) \
+ case dwarf::NAME: \
+ Attrs.NAME = V; \
+ break;
+#include "DIEHashAttributes.def"
default:
break;
}
@@ -366,62 +318,12 @@ void DIEHash::hashAttribute(const DIEValue &Value, dwarf::Tag Tag) {
// Go through the attributes from \param Attrs in the order specified in 7.27.4
// and hash them.
void DIEHash::hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag) {
-#define ADD_ATTR(ATTR) \
+#define HANDLE_DIE_HASH_ATTR(NAME) \
{ \
- if (ATTR) \
- hashAttribute(ATTR, Tag); \
+ if (Attrs.NAME) \
+ hashAttribute(Attrs.NAME, Tag); \
}
-
- ADD_ATTR(Attrs.DW_AT_name);
- ADD_ATTR(Attrs.DW_AT_accessibility);
- ADD_ATTR(Attrs.DW_AT_address_class);
- ADD_ATTR(Attrs.DW_AT_allocated);
- ADD_ATTR(Attrs.DW_AT_artificial);
- ADD_ATTR(Attrs.DW_AT_associated);
- ADD_ATTR(Attrs.DW_AT_binary_scale);
- ADD_ATTR(Attrs.DW_AT_bit_offset);
- ADD_ATTR(Attrs.DW_AT_bit_size);
- ADD_ATTR(Attrs.DW_AT_bit_stride);
- ADD_ATTR(Attrs.DW_AT_byte_size);
- ADD_ATTR(Attrs.DW_AT_byte_stride);
- ADD_ATTR(Attrs.DW_AT_const_expr);
- ADD_ATTR(Attrs.DW_AT_const_value);
- ADD_ATTR(Attrs.DW_AT_containing_type);
- ADD_ATTR(Attrs.DW_AT_count);
- ADD_ATTR(Attrs.DW_AT_data_bit_offset);
- ADD_ATTR(Attrs.DW_AT_data_location);
- ADD_ATTR(Attrs.DW_AT_data_member_location);
- ADD_ATTR(Attrs.DW_AT_decimal_scale);
- ADD_ATTR(Attrs.DW_AT_decimal_sign);
- ADD_ATTR(Attrs.DW_AT_default_value);
- ADD_ATTR(Attrs.DW_AT_digit_count);
- ADD_ATTR(Attrs.DW_AT_discr);
- ADD_ATTR(Attrs.DW_AT_discr_list);
- ADD_ATTR(Attrs.DW_AT_discr_value);
- ADD_ATTR(Attrs.DW_AT_encoding);
- ADD_ATTR(Attrs.DW_AT_enum_class);
- ADD_ATTR(Attrs.DW_AT_endianity);
- ADD_ATTR(Attrs.DW_AT_explicit);
- ADD_ATTR(Attrs.DW_AT_is_optional);
- ADD_ATTR(Attrs.DW_AT_location);
- ADD_ATTR(Attrs.DW_AT_lower_bound);
- ADD_ATTR(Attrs.DW_AT_mutable);
- ADD_ATTR(Attrs.DW_AT_ordering);
- ADD_ATTR(Attrs.DW_AT_picture_string);
- ADD_ATTR(Attrs.DW_AT_prototyped);
- ADD_ATTR(Attrs.DW_AT_small);
- ADD_ATTR(Attrs.DW_AT_segment);
- ADD_ATTR(Attrs.DW_AT_string_length);
- ADD_ATTR(Attrs.DW_AT_threads_scaled);
- ADD_ATTR(Attrs.DW_AT_upper_bound);
- ADD_ATTR(Attrs.DW_AT_use_location);
- ADD_ATTR(Attrs.DW_AT_use_UTF8);
- ADD_ATTR(Attrs.DW_AT_variable_parameter);
- ADD_ATTR(Attrs.DW_AT_virtuality);
- ADD_ATTR(Attrs.DW_AT_visibility);
- ADD_ATTR(Attrs.DW_AT_vtable_elem_location);
- ADD_ATTR(Attrs.DW_AT_type);
-
+#include "DIEHashAttributes.def"
// FIXME: Add the extended attributes.
}
@@ -478,10 +380,12 @@ void DIEHash::computeHash(const DIE &Die) {
/// DWARF4 standard. It is an md5 hash of the flattened description of the DIE
/// with the inclusion of the full CU and all top level CU entities.
// TODO: Initialize the type chain at 0 instead of 1 for CU signatures.
-uint64_t DIEHash::computeCUSignature(const DIE &Die) {
+uint64_t DIEHash::computeCUSignature(StringRef DWOName, const DIE &Die) {
Numbering.clear();
Numbering[&Die] = 1;
+ if (!DWOName.empty())
+ Hash.update(DWOName);
// Hash the DIE.
computeHash(Die);
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.h b/lib/CodeGen/AsmPrinter/DIEHash.h
index 996cd7ef3d2e..29337ae38a99 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.h
+++ b/lib/CodeGen/AsmPrinter/DIEHash.h
@@ -28,64 +28,15 @@ class CompileUnit;
class DIEHash {
// Collection of all attributes used in hashing a particular DIE.
struct DIEAttrs {
- DIEValue DW_AT_name;
- DIEValue DW_AT_accessibility;
- DIEValue DW_AT_address_class;
- DIEValue DW_AT_allocated;
- DIEValue DW_AT_artificial;
- DIEValue DW_AT_associated;
- DIEValue DW_AT_binary_scale;
- DIEValue DW_AT_bit_offset;
- DIEValue DW_AT_bit_size;
- DIEValue DW_AT_bit_stride;
- DIEValue DW_AT_byte_size;
- DIEValue DW_AT_byte_stride;
- DIEValue DW_AT_const_expr;
- DIEValue DW_AT_const_value;
- DIEValue DW_AT_containing_type;
- DIEValue DW_AT_count;
- DIEValue DW_AT_data_bit_offset;
- DIEValue DW_AT_data_location;
- DIEValue DW_AT_data_member_location;
- DIEValue DW_AT_decimal_scale;
- DIEValue DW_AT_decimal_sign;
- DIEValue DW_AT_default_value;
- DIEValue DW_AT_digit_count;
- DIEValue DW_AT_discr;
- DIEValue DW_AT_discr_list;
- DIEValue DW_AT_discr_value;
- DIEValue DW_AT_encoding;
- DIEValue DW_AT_enum_class;
- DIEValue DW_AT_endianity;
- DIEValue DW_AT_explicit;
- DIEValue DW_AT_is_optional;
- DIEValue DW_AT_location;
- DIEValue DW_AT_lower_bound;
- DIEValue DW_AT_mutable;
- DIEValue DW_AT_ordering;
- DIEValue DW_AT_picture_string;
- DIEValue DW_AT_prototyped;
- DIEValue DW_AT_small;
- DIEValue DW_AT_segment;
- DIEValue DW_AT_string_length;
- DIEValue DW_AT_threads_scaled;
- DIEValue DW_AT_upper_bound;
- DIEValue DW_AT_use_location;
- DIEValue DW_AT_use_UTF8;
- DIEValue DW_AT_variable_parameter;
- DIEValue DW_AT_virtuality;
- DIEValue DW_AT_visibility;
- DIEValue DW_AT_vtable_elem_location;
- DIEValue DW_AT_type;
-
- // Insert any additional ones here...
+#define HANDLE_DIE_HASH_ATTR(NAME) DIEValue NAME;
+#include "DIEHashAttributes.def"
};
public:
DIEHash(AsmPrinter *A = nullptr) : AP(A) {}
/// \brief Computes the CU signature.
- uint64_t computeCUSignature(const DIE &Die);
+ uint64_t computeCUSignature(StringRef DWOName, const DIE &Die);
/// \brief Computes the type signature.
uint64_t computeTypeSignature(const DIE &Die);
diff --git a/lib/CodeGen/AsmPrinter/DIEHashAttributes.def b/lib/CodeGen/AsmPrinter/DIEHashAttributes.def
new file mode 100644
index 000000000000..28a02390fccb
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/DIEHashAttributes.def
@@ -0,0 +1,55 @@
+#ifndef HANDLE_DIE_HASH_ATTR
+#error "Missing macro definition of HANDLE_DIE_HASH_ATTR"
+#endif
+
+HANDLE_DIE_HASH_ATTR(DW_AT_name)
+HANDLE_DIE_HASH_ATTR(DW_AT_accessibility)
+HANDLE_DIE_HASH_ATTR(DW_AT_address_class)
+HANDLE_DIE_HASH_ATTR(DW_AT_allocated)
+HANDLE_DIE_HASH_ATTR(DW_AT_artificial)
+HANDLE_DIE_HASH_ATTR(DW_AT_associated)
+HANDLE_DIE_HASH_ATTR(DW_AT_binary_scale)
+HANDLE_DIE_HASH_ATTR(DW_AT_bit_offset)
+HANDLE_DIE_HASH_ATTR(DW_AT_bit_size)
+HANDLE_DIE_HASH_ATTR(DW_AT_bit_stride)
+HANDLE_DIE_HASH_ATTR(DW_AT_byte_size)
+HANDLE_DIE_HASH_ATTR(DW_AT_byte_stride)
+HANDLE_DIE_HASH_ATTR(DW_AT_const_expr)
+HANDLE_DIE_HASH_ATTR(DW_AT_const_value)
+HANDLE_DIE_HASH_ATTR(DW_AT_containing_type)
+HANDLE_DIE_HASH_ATTR(DW_AT_count)
+HANDLE_DIE_HASH_ATTR(DW_AT_data_bit_offset)
+HANDLE_DIE_HASH_ATTR(DW_AT_data_location)
+HANDLE_DIE_HASH_ATTR(DW_AT_data_member_location)
+HANDLE_DIE_HASH_ATTR(DW_AT_decimal_scale)
+HANDLE_DIE_HASH_ATTR(DW_AT_decimal_sign)
+HANDLE_DIE_HASH_ATTR(DW_AT_default_value)
+HANDLE_DIE_HASH_ATTR(DW_AT_digit_count)
+HANDLE_DIE_HASH_ATTR(DW_AT_discr)
+HANDLE_DIE_HASH_ATTR(DW_AT_discr_list)
+HANDLE_DIE_HASH_ATTR(DW_AT_discr_value)
+HANDLE_DIE_HASH_ATTR(DW_AT_encoding)
+HANDLE_DIE_HASH_ATTR(DW_AT_enum_class)
+HANDLE_DIE_HASH_ATTR(DW_AT_endianity)
+HANDLE_DIE_HASH_ATTR(DW_AT_explicit)
+HANDLE_DIE_HASH_ATTR(DW_AT_is_optional)
+HANDLE_DIE_HASH_ATTR(DW_AT_location)
+HANDLE_DIE_HASH_ATTR(DW_AT_lower_bound)
+HANDLE_DIE_HASH_ATTR(DW_AT_mutable)
+HANDLE_DIE_HASH_ATTR(DW_AT_ordering)
+HANDLE_DIE_HASH_ATTR(DW_AT_picture_string)
+HANDLE_DIE_HASH_ATTR(DW_AT_prototyped)
+HANDLE_DIE_HASH_ATTR(DW_AT_small)
+HANDLE_DIE_HASH_ATTR(DW_AT_segment)
+HANDLE_DIE_HASH_ATTR(DW_AT_string_length)
+HANDLE_DIE_HASH_ATTR(DW_AT_threads_scaled)
+HANDLE_DIE_HASH_ATTR(DW_AT_upper_bound)
+HANDLE_DIE_HASH_ATTR(DW_AT_use_location)
+HANDLE_DIE_HASH_ATTR(DW_AT_use_UTF8)
+HANDLE_DIE_HASH_ATTR(DW_AT_variable_parameter)
+HANDLE_DIE_HASH_ATTR(DW_AT_virtuality)
+HANDLE_DIE_HASH_ATTR(DW_AT_visibility)
+HANDLE_DIE_HASH_ATTR(DW_AT_vtable_elem_location)
+HANDLE_DIE_HASH_ATTR(DW_AT_type)
+
+#undef HANDLE_DIE_HASH_ATTR
diff --git a/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index 826162ad47c4..0971c5942203 100644
--- a/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -115,7 +115,8 @@ uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) {
return getBaseTypeSize(BaseType);
}
-bool hasDebugInfo(const MachineModuleInfo *MMI, const MachineFunction *MF) {
+static bool hasDebugInfo(const MachineModuleInfo *MMI,
+ const MachineFunction *MF) {
if (!MMI->hasDebugInfo())
return false;
auto *SP = MF->getFunction()->getSubprogram();
@@ -223,9 +224,9 @@ void DebugHandlerBase::endInstruction() {
return;
assert(CurMI != nullptr);
- // Don't create a new label after DBG_VALUE instructions.
- // They don't generate code.
- if (!CurMI->isDebugValue()) {
+ // Don't create a new label after DBG_VALUE and other instructions that don't
+ // generate code.
+ if (!CurMI->isMetaInstruction()) {
PrevLabel = nullptr;
PrevInstBB = CurMI->getParent();
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index e172712cf889..04073b3aed68 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -760,7 +760,7 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) {
/// addGlobalName - Add a new global name to the compile unit.
void DwarfCompileUnit::addGlobalName(StringRef Name, const DIE &Die,
const DIScope *Context) {
- if (includeMinimalInlineScopes())
+ if (!DD->hasDwarfPubSections(includeMinimalInlineScopes()))
return;
std::string FullName = getParentContextString(Context) + Name.str();
GlobalNames[FullName] = &Die;
@@ -768,7 +768,7 @@ void DwarfCompileUnit::addGlobalName(StringRef Name, const DIE &Die,
void DwarfCompileUnit::addGlobalNameForTypeUnit(StringRef Name,
const DIScope *Context) {
- if (includeMinimalInlineScopes())
+ if (!DD->hasDwarfPubSections(includeMinimalInlineScopes()))
return;
std::string FullName = getParentContextString(Context) + Name.str();
// Insert, allowing the entry to remain as-is if it's already present
@@ -781,7 +781,7 @@ void DwarfCompileUnit::addGlobalNameForTypeUnit(StringRef Name,
/// Add a new global type to the unit.
void DwarfCompileUnit::addGlobalType(const DIType *Ty, const DIE &Die,
const DIScope *Context) {
- if (includeMinimalInlineScopes())
+ if (!DD->hasDwarfPubSections(includeMinimalInlineScopes()))
return;
std::string FullName = getParentContextString(Context) + Ty->getName().str();
GlobalTypes[FullName] = &Die;
@@ -789,7 +789,7 @@ void DwarfCompileUnit::addGlobalType(const DIType *Ty, const DIE &Die,
void DwarfCompileUnit::addGlobalTypeUnitType(const DIType *Ty,
const DIScope *Context) {
- if (includeMinimalInlineScopes())
+ if (!DD->hasDwarfPubSections(includeMinimalInlineScopes()))
return;
std::string FullName = getParentContextString(Context) + Ty->getName().str();
// Insert, allowing the entry to remain as-is if it's already present
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 77e9e671529f..b8f57472f17c 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -77,8 +77,6 @@ class DwarfCompileUnit final : public DwarfUnit {
bool isDwoUnit() const override;
- bool includeMinimalInlineScopes() const;
-
DenseMap<const MDNode *, DIE *> &getAbstractSPDies() {
if (isDwoUnit() && !DD->shareAcrossDWOCUs())
return AbstractSPDies;
@@ -101,6 +99,8 @@ public:
return Skeleton;
}
+ bool includeMinimalInlineScopes() const;
+
void initStmtList();
/// Apply the DW_AT_stmt_list from this compile unit to the specified DIE.
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 3410b98d7776..bf27516e1ccd 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -252,12 +252,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
// Handle split DWARF.
HasSplitDwarf = !Asm->TM.Options.MCOptions.SplitDwarfFile.empty();
- // Pubnames/pubtypes on by default for GDB.
- if (DwarfPubSections == Default)
- HasDwarfPubSections = tuneForGDB();
- else
- HasDwarfPubSections = DwarfPubSections == Enable;
-
// SCE defaults to linkage names only for abstract subprograms.
if (DwarfLinkageNames == DefaultLinkageNames)
UseAllLinkageNames = !tuneForSCE();
@@ -380,19 +374,35 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU,
// Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram
// was inlined from another compile unit.
- auto &CU = *CUMap.lookup(SP->getUnit());
- if (auto *SkelCU = CU.getSkeleton()) {
- (shareAcrossDWOCUs() ? CU : SrcCU)
- .constructAbstractSubprogramScopeDIE(Scope);
- if (CU.getCUNode()->getSplitDebugInlining())
- SkelCU->constructAbstractSubprogramScopeDIE(Scope);
- } else {
- CU.constructAbstractSubprogramScopeDIE(Scope);
+ if (useSplitDwarf() && !shareAcrossDWOCUs() && !SP->getUnit()->getSplitDebugInlining())
+ // Avoid building the original CU if it won't be used
+ SrcCU.constructAbstractSubprogramScopeDIE(Scope);
+ else {
+ auto &CU = getOrCreateDwarfCompileUnit(SP->getUnit());
+ if (auto *SkelCU = CU.getSkeleton()) {
+ (shareAcrossDWOCUs() ? CU : SrcCU)
+ .constructAbstractSubprogramScopeDIE(Scope);
+ if (CU.getCUNode()->getSplitDebugInlining())
+ SkelCU->constructAbstractSubprogramScopeDIE(Scope);
+ } else
+ CU.constructAbstractSubprogramScopeDIE(Scope);
}
}
-void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const {
- if (!GenerateGnuPubSections)
+bool DwarfDebug::hasDwarfPubSections(bool includeMinimalInlineScopes) const {
+ // Opting in to GNU Pubnames/types overrides the default to ensure these are
+ // generated for things like Gold's gdb_index generation.
+ if (GenerateGnuPubSections)
+ return true;
+
+ if (DwarfPubSections == Default)
+ return tuneForGDB() && !includeMinimalInlineScopes;
+
+ return DwarfPubSections == Enable;
+}
+
+void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const {
+ if (!hasDwarfPubSections(U.includeMinimalInlineScopes()))
return;
U.addFlag(D, dwarf::DW_AT_GNU_pubnames);
@@ -401,7 +411,9 @@ void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const {
// Create new DwarfCompileUnit for the given metadata node with tag
// DW_TAG_compile_unit.
DwarfCompileUnit &
-DwarfDebug::constructDwarfCompileUnit(const DICompileUnit *DIUnit) {
+DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
+ if (auto *CU = CUMap.lookup(DIUnit))
+ return *CU;
StringRef FN = DIUnit->getFilename();
CompilationDir = DIUnit->getDirectory();
@@ -534,7 +546,12 @@ void DwarfDebug::beginModule() {
}
for (DICompileUnit *CUNode : M->debug_compile_units()) {
- DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode);
+ if (CUNode->getEnumTypes().empty() && CUNode->getRetainedTypes().empty() &&
+ CUNode->getGlobalVariables().empty() &&
+ CUNode->getImportedEntities().empty() && CUNode->getMacros().empty())
+ continue;
+
+ DwarfCompileUnit &CU = getOrCreateDwarfCompileUnit(CUNode);
for (auto *IE : CUNode->getImportedEntities())
CU.addImportedEntity(IE);
@@ -581,11 +598,12 @@ void DwarfDebug::finishVariableDefinitions() {
}
void DwarfDebug::finishSubprogramDefinitions() {
- for (const DISubprogram *SP : ProcessedSPNodes)
- if (SP->getUnit()->getEmissionKind() != DICompileUnit::NoDebug)
- forBothCUs(*CUMap.lookup(SP->getUnit()), [&](DwarfCompileUnit &CU) {
- CU.finishSubprogramDefinition(SP);
- });
+ for (const DISubprogram *SP : ProcessedSPNodes) {
+ assert(SP->getUnit()->getEmissionKind() != DICompileUnit::NoDebug);
+ forBothCUs(
+ getOrCreateDwarfCompileUnit(SP->getUnit()),
+ [&](DwarfCompileUnit &CU) { CU.finishSubprogramDefinition(SP); });
+ }
}
void DwarfDebug::finalizeModuleInfo() {
@@ -595,6 +613,13 @@ void DwarfDebug::finalizeModuleInfo() {
finishVariableDefinitions();
+ // Include the DWO file name in the hash if there's more than one CU.
+ // This handles ThinLTO's situation where imported CUs may very easily be
+ // duplicate with the same CU partially imported into another ThinLTO unit.
+ StringRef DWOName;
+ if (CUMap.size() > 1)
+ DWOName = Asm->TM.Options.MCOptions.SplitDwarfFile;
+
// Handle anything that needs to be done on a per-unit basis after
// all other generation.
for (const auto &P : CUMap) {
@@ -609,7 +634,8 @@ void DwarfDebug::finalizeModuleInfo() {
auto *SkCU = TheCU.getSkeleton();
if (useSplitDwarf()) {
// Emit a unique identifier for this CU.
- uint64_t ID = DIEHash(Asm).computeCUSignature(TheCU.getUnitDie());
+ uint64_t ID =
+ DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie());
TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
dwarf::DW_FORM_data8, ID);
SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
@@ -718,7 +744,9 @@ void DwarfDebug::endModule() {
}
// Emit the pubnames and pubtypes sections if requested.
- if (HasDwarfPubSections) {
+ // The condition is optimistically correct - any CU not using GMLT (&
+ // implicit/default pubnames state) might still have pubnames.
+ if (hasDwarfPubSections(/* gmlt */ false)) {
emitDebugPubNames(GenerateGnuPubSections);
emitDebugPubTypes(GenerateGnuPubSections);
}
@@ -1028,8 +1056,12 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
DebugHandlerBase::beginInstruction(MI);
assert(CurMI);
+ const auto *SP = MI->getParent()->getParent()->getFunction()->getSubprogram();
+ if (!SP || SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug)
+ return;
+
// Check if source location changes, but ignore DBG_VALUE and CFI locations.
- if (MI->isDebugValue() || MI->isCFIInstruction())
+ if (MI->isMetaInstruction())
return;
const DebugLoc &DL = MI->getDebugLoc();
// When we emit a line-0 record, we don't update PrevInstLoc; so look at
@@ -1111,7 +1143,7 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
// the beginning of the function body.
for (const auto &MBB : *MF)
for (const auto &MI : MBB)
- if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
+ if (!MI.isMetaInstruction() && !MI.getFlag(MachineInstr::FrameSetup) &&
MI.getDebugLoc())
return MI.getDebugLoc();
return DebugLoc();
@@ -1122,40 +1154,28 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) {
CurFn = MF;
- if (LScopes.empty())
+ auto *SP = MF->getFunction()->getSubprogram();
+ assert(LScopes.empty() || SP == LScopes.getCurrentFunctionScope()->getScopeNode());
+ if (SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug)
return;
+ DwarfCompileUnit &CU = getOrCreateDwarfCompileUnit(SP->getUnit());
+
// Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function
// belongs to so that we add to the correct per-cu line table in the
// non-asm case.
- LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
- // FnScope->getScopeNode() and DI->second should represent the same function,
- // though they may not be the same MDNode due to inline functions merged in
- // LTO where the debug info metadata still differs (either due to distinct
- // written differences - two versions of a linkonce_odr function
- // written/copied into two separate files, or some sub-optimal metadata that
- // isn't structurally identical (see: file path/name info from clang, which
- // includes the directory of the cpp file being built, even when the file name
- // is absolute (such as an <> lookup header)))
- auto *SP = cast<DISubprogram>(FnScope->getScopeNode());
- DwarfCompileUnit *TheCU = CUMap.lookup(SP->getUnit());
- if (!TheCU) {
- assert(SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug &&
- "DICompileUnit missing from llvm.dbg.cu?");
- return;
- }
if (Asm->OutStreamer->hasRawTextSupport())
// Use a single line table if we are generating assembly.
Asm->OutStreamer->getContext().setDwarfCompileUnitID(0);
else
- Asm->OutStreamer->getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
+ Asm->OutStreamer->getContext().setDwarfCompileUnitID(CU.getUniqueID());
// Record beginning of function.
PrologEndLoc = findPrologueEndLoc(MF);
- if (DILocation *L = PrologEndLoc) {
+ if (PrologEndLoc) {
// We'd like to list the prologue as "not statements" but GDB behaves
// poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
- auto *SP = L->getInlinedAtScope()->getSubprogram();
+ auto *SP = PrologEndLoc->getInlinedAtScope()->getSubprogram();
recordSourceLine(SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT);
}
}
@@ -1395,7 +1415,7 @@ void DwarfDebug::emitDebugPubSection(
const auto &Globals = (TheU->*Accessor)();
- if (Globals.empty())
+ if (!hasDwarfPubSections(TheU->includeMinimalInlineScopes()))
continue;
if (auto *Skeleton = TheU->getSkeleton())
@@ -1544,6 +1564,9 @@ void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
// Emit locations into the debug loc section.
void DwarfDebug::emitDebugLoc() {
+ if (DebugLocs.getLists().empty())
+ return;
+
// Start the dwarf loc section.
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
@@ -1755,6 +1778,9 @@ void DwarfDebug::emitDebugARanges() {
/// Emit address ranges into a debug ranges section.
void DwarfDebug::emitDebugRanges() {
+ if (CUMap.empty())
+ return;
+
// Start the dwarf ranges section.
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
@@ -1834,6 +1860,9 @@ void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) {
/// Emit macros into a debug macinfo section.
void DwarfDebug::emitDebugMacinfo() {
+ if (CUMap.empty())
+ return;
+
// Start the dwarf macinfo section.
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfMacinfoSection());
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index b9c5aa9ffb23..ebfba4cfc275 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -246,9 +246,6 @@ class DwarfDebug : public DebugHandlerBase {
std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
TypeUnitsUnderConstruction;
- /// Whether to emit the pubnames/pubtypes sections.
- bool HasDwarfPubSections;
-
/// Whether to use the GNU TLS opcode (instead of the standard opcode).
bool UseGNUTLSOpcode;
@@ -415,11 +412,11 @@ class DwarfDebug : public DebugHandlerBase {
/// Flags to let the linker know we have emitted new style pubnames. Only
/// emit it here if we don't have a skeleton CU for split dwarf.
- void addGnuPubAttributes(DwarfUnit &U, DIE &D) const;
+ void addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const;
/// Create new DwarfCompileUnit for the given metadata node with tag
/// DW_TAG_compile_unit.
- DwarfCompileUnit &constructDwarfCompileUnit(const DICompileUnit *DIUnit);
+ DwarfCompileUnit &getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit);
/// Construct imported_module or imported_declaration DIE.
void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
@@ -556,6 +553,8 @@ public:
/// A helper function to check whether the DIE for a given Scope is
/// going to be null.
bool isLexicalScopeDIENull(LexicalScope *Scope);
+
+ bool hasDwarfPubSections(bool includeMinimalInlineScopes) const;
};
} // End of namespace llvm
diff --git a/lib/CodeGen/AtomicExpandPass.cpp b/lib/CodeGen/AtomicExpandPass.cpp
index 984973cf3a3b..344136b1f195 100644
--- a/lib/CodeGen/AtomicExpandPass.cpp
+++ b/lib/CodeGen/AtomicExpandPass.cpp
@@ -96,7 +96,7 @@ namespace {
char AtomicExpand::ID = 0;
char &llvm::AtomicExpandID = AtomicExpand::ID;
-INITIALIZE_PASS(AtomicExpand, "atomic-expand", "Expand Atomic instructions",
+INITIALIZE_PASS(AtomicExpand, DEBUG_TYPE, "Expand Atomic instructions",
false, false)
FunctionPass *llvm::createAtomicExpandPass() { return new AtomicExpand(); }
diff --git a/lib/CodeGen/BasicTargetTransformInfo.cpp b/lib/CodeGen/BasicTargetTransformInfo.cpp
index a67e194356d8..d3fced436b68 100644
--- a/lib/CodeGen/BasicTargetTransformInfo.cpp
+++ b/lib/CodeGen/BasicTargetTransformInfo.cpp
@@ -24,8 +24,6 @@
#include <utility>
using namespace llvm;
-#define DEBUG_TYPE "basictti"
-
// This flag is used by the template base class for BasicTTIImpl, and here to
// provide a definition.
cl::opt<unsigned>
diff --git a/lib/CodeGen/BranchCoalescing.cpp b/lib/CodeGen/BranchCoalescing.cpp
index efdf300df850..2c41b597843c 100644
--- a/lib/CodeGen/BranchCoalescing.cpp
+++ b/lib/CodeGen/BranchCoalescing.cpp
@@ -27,7 +27,7 @@
using namespace llvm;
-#define DEBUG_TYPE "coal-branch"
+#define DEBUG_TYPE "branch-coalescing"
static cl::opt<cl::boolOrDefault>
EnableBranchCoalescing("enable-branch-coalesce", cl::Hidden,
@@ -193,11 +193,11 @@ public:
char BranchCoalescing::ID = 0;
char &llvm::BranchCoalescingID = BranchCoalescing::ID;
-INITIALIZE_PASS_BEGIN(BranchCoalescing, "branch-coalescing",
+INITIALIZE_PASS_BEGIN(BranchCoalescing, DEBUG_TYPE,
"Branch Coalescing", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
-INITIALIZE_PASS_END(BranchCoalescing, "branch-coalescing", "Branch Coalescing",
+INITIALIZE_PASS_END(BranchCoalescing, DEBUG_TYPE, "Branch Coalescing",
false, false)
BranchCoalescing::CoalescingCandidateInfo::CoalescingCandidateInfo()
diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp
index b63d9f4a4351..03ceac10beec 100644
--- a/lib/CodeGen/BranchFolding.cpp
+++ b/lib/CodeGen/BranchFolding.cpp
@@ -44,7 +44,7 @@
#include <algorithm>
using namespace llvm;
-#define DEBUG_TYPE "branchfolding"
+#define DEBUG_TYPE "branch-folder"
STATISTIC(NumDeadBlocks, "Number of dead blocks removed");
STATISTIC(NumBranchOpts, "Number of branches optimized");
@@ -89,7 +89,7 @@ namespace {
char BranchFolderPass::ID = 0;
char &llvm::BranchFolderPassID = BranchFolderPass::ID;
-INITIALIZE_PASS(BranchFolderPass, "branch-folder",
+INITIALIZE_PASS(BranchFolderPass, DEBUG_TYPE,
"Control Flow Optimizer", false, false)
bool BranchFolderPass::runOnMachineFunction(MachineFunction &MF) {
@@ -153,13 +153,14 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF,
TriedMerging.clear();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
AfterBlockPlacement = AfterPlacement;
TII = tii;
TRI = tri;
MMI = mmi;
MLI = mli;
+ this->MRI = &MRI;
- MachineRegisterInfo &MRI = MF.getRegInfo();
UpdateLiveIns = MRI.tracksLiveness() && TRI->trackLivenessAfterRegAlloc(MF);
if (!UpdateLiveIns)
MRI.invalidateLiveness();
@@ -351,7 +352,7 @@ void BranchFolder::ReplaceTailWithBranchTo(MachineBasicBlock::iterator OldInst,
if (UpdateLiveIns) {
NewDest->clearLiveIns();
- computeLiveIns(LiveRegs, *TRI, *NewDest);
+ computeLiveIns(LiveRegs, *MRI, *NewDest);
}
++NumTailMerge;
@@ -388,7 +389,7 @@ MachineBasicBlock *BranchFolder::SplitMBBAt(MachineBasicBlock &CurMBB,
MBBFreqInfo.setBlockFreq(NewMBB, MBBFreqInfo.getBlockFreq(&CurMBB));
if (UpdateLiveIns)
- computeLiveIns(LiveRegs, *TRI, *NewMBB);
+ computeLiveIns(LiveRegs, *MRI, *NewMBB);
// Add the new block to the funclet.
const auto &FuncletI = FuncletMembership.find(&CurMBB);
diff --git a/lib/CodeGen/BranchFolding.h b/lib/CodeGen/BranchFolding.h
index 4852721eea10..92681137e4c6 100644
--- a/lib/CodeGen/BranchFolding.h
+++ b/lib/CodeGen/BranchFolding.h
@@ -108,6 +108,7 @@ namespace llvm {
bool UpdateLiveIns;
unsigned MinCommonTailLength;
const TargetInstrInfo *TII;
+ const MachineRegisterInfo *MRI;
const TargetRegisterInfo *TRI;
MachineModuleInfo *MMI;
MachineLoopInfo *MLI;
diff --git a/lib/CodeGen/BranchRelaxation.cpp b/lib/CodeGen/BranchRelaxation.cpp
index 7af136941661..e3de61c7816f 100644
--- a/lib/CodeGen/BranchRelaxation.cpp
+++ b/lib/CodeGen/BranchRelaxation.cpp
@@ -259,7 +259,7 @@ MachineBasicBlock *BranchRelaxation::splitBlockBeforeInstr(MachineInstr &MI,
// Need to fix live-in lists if we track liveness.
if (TRI->trackLivenessAfterRegAlloc(*MF))
- computeLiveIns(LiveRegs, *TRI, *NewBB);
+ computeLiveIns(LiveRegs, MF->getRegInfo(), *NewBB);
++NumSplit;
@@ -345,6 +345,10 @@ bool BranchRelaxation::fixupConditionalBranch(MachineInstr &MI) {
// Do it here since if there's no split, no update is needed.
MBB->replaceSuccessor(FBB, &NewBB);
NewBB.addSuccessor(FBB);
+
+ // Need to fix live-in lists if we track liveness.
+ if (TRI->trackLivenessAfterRegAlloc(*MF))
+ computeLiveIns(LiveRegs, MF->getRegInfo(), NewBB);
}
// We now have an appropriate fall-through block in place (either naturally or
diff --git a/lib/CodeGen/CodeGenPrepare.cpp b/lib/CodeGen/CodeGenPrepare.cpp
index 3a1a3020a8d4..4e85708efafc 100644
--- a/lib/CodeGen/CodeGenPrepare.cpp
+++ b/lib/CodeGen/CodeGenPrepare.cpp
@@ -257,10 +257,10 @@ class TypePromotionTransaction;
}
char CodeGenPrepare::ID = 0;
-INITIALIZE_PASS_BEGIN(CodeGenPrepare, "codegenprepare",
+INITIALIZE_PASS_BEGIN(CodeGenPrepare, DEBUG_TYPE,
"Optimize for code generation", false, false)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
-INITIALIZE_PASS_END(CodeGenPrepare, "codegenprepare",
+INITIALIZE_PASS_END(CodeGenPrepare, DEBUG_TYPE,
"Optimize for code generation", false, false)
FunctionPass *llvm::createCodeGenPreparePass() { return new CodeGenPrepare(); }
diff --git a/lib/CodeGen/DeadMachineInstructionElim.cpp b/lib/CodeGen/DeadMachineInstructionElim.cpp
index 7ac2e5445435..265dda16bfa7 100644
--- a/lib/CodeGen/DeadMachineInstructionElim.cpp
+++ b/lib/CodeGen/DeadMachineInstructionElim.cpp
@@ -23,7 +23,7 @@
using namespace llvm;
-#define DEBUG_TYPE "codegen-dce"
+#define DEBUG_TYPE "dead-mi-elimination"
STATISTIC(NumDeletes, "Number of dead instructions deleted");
@@ -54,7 +54,7 @@ namespace {
char DeadMachineInstructionElim::ID = 0;
char &llvm::DeadMachineInstructionElimID = DeadMachineInstructionElim::ID;
-INITIALIZE_PASS(DeadMachineInstructionElim, "dead-mi-elimination",
+INITIALIZE_PASS(DeadMachineInstructionElim, DEBUG_TYPE,
"Remove dead machine instructions", false, false)
bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const {
diff --git a/lib/CodeGen/DetectDeadLanes.cpp b/lib/CodeGen/DetectDeadLanes.cpp
index 6f4ea1912cf4..ab9a0592e017 100644
--- a/lib/CodeGen/DetectDeadLanes.cpp
+++ b/lib/CodeGen/DetectDeadLanes.cpp
@@ -132,8 +132,7 @@ private:
char DetectDeadLanes::ID = 0;
char &llvm::DetectDeadLanesID = DetectDeadLanes::ID;
-INITIALIZE_PASS(DetectDeadLanes, "detect-dead-lanes", "Detect Dead Lanes",
- false, false)
+INITIALIZE_PASS(DetectDeadLanes, DEBUG_TYPE, "Detect Dead Lanes", false, false)
/// Returns true if \p MI will get lowered to a series of COPY instructions.
/// We call this a COPY-like instruction.
diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp
index 1ef4d8660657..06ae5cd72c85 100644
--- a/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/lib/CodeGen/DwarfEHPrepare.cpp
@@ -71,12 +71,12 @@ namespace {
} // end anonymous namespace
char DwarfEHPrepare::ID = 0;
-INITIALIZE_PASS_BEGIN(DwarfEHPrepare, "dwarfehprepare",
+INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
"Prepare DWARF exceptions", false, false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
-INITIALIZE_PASS_END(DwarfEHPrepare, "dwarfehprepare",
+INITIALIZE_PASS_END(DwarfEHPrepare, DEBUG_TYPE,
"Prepare DWARF exceptions", false, false)
FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
diff --git a/lib/CodeGen/EarlyIfConversion.cpp b/lib/CodeGen/EarlyIfConversion.cpp
index 729172796453..402afe75b141 100644
--- a/lib/CodeGen/EarlyIfConversion.cpp
+++ b/lib/CodeGen/EarlyIfConversion.cpp
@@ -616,13 +616,13 @@ private:
char EarlyIfConverter::ID = 0;
char &llvm::EarlyIfConverterID = EarlyIfConverter::ID;
-INITIALIZE_PASS_BEGIN(EarlyIfConverter,
- "early-ifcvt", "Early If Converter", false, false)
+INITIALIZE_PASS_BEGIN(EarlyIfConverter, DEBUG_TYPE,
+ "Early If Converter", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachineTraceMetrics)
-INITIALIZE_PASS_END(EarlyIfConverter,
- "early-ifcvt", "Early If Converter", false, false)
+INITIALIZE_PASS_END(EarlyIfConverter, DEBUG_TYPE,
+ "Early If Converter", false, false)
void EarlyIfConverter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<MachineBranchProbabilityInfo>();
diff --git a/lib/CodeGen/ExpandISelPseudos.cpp b/lib/CodeGen/ExpandISelPseudos.cpp
index 0ec79c2e69f9..88d422a0f545 100644
--- a/lib/CodeGen/ExpandISelPseudos.cpp
+++ b/lib/CodeGen/ExpandISelPseudos.cpp
@@ -41,7 +41,7 @@ namespace {
char ExpandISelPseudos::ID = 0;
char &llvm::ExpandISelPseudosID = ExpandISelPseudos::ID;
-INITIALIZE_PASS(ExpandISelPseudos, "expand-isel-pseudos",
+INITIALIZE_PASS(ExpandISelPseudos, DEBUG_TYPE,
"Expand ISel Pseudo-instructions", false, false)
bool ExpandISelPseudos::runOnMachineFunction(MachineFunction &MF) {
diff --git a/lib/CodeGen/ExpandPostRAPseudos.cpp b/lib/CodeGen/ExpandPostRAPseudos.cpp
index e860906043dd..27cd639b2a49 100644
--- a/lib/CodeGen/ExpandPostRAPseudos.cpp
+++ b/lib/CodeGen/ExpandPostRAPseudos.cpp
@@ -58,7 +58,7 @@ private:
char ExpandPostRA::ID = 0;
char &llvm::ExpandPostRAPseudosID = ExpandPostRA::ID;
-INITIALIZE_PASS(ExpandPostRA, "postrapseudos",
+INITIALIZE_PASS(ExpandPostRA, DEBUG_TYPE,
"Post-RA pseudo instruction expansion pass", false, false)
/// TransferImplicitOperands - MI is a pseudo-instruction, and the lowered
diff --git a/lib/CodeGen/FuncletLayout.cpp b/lib/CodeGen/FuncletLayout.cpp
index d61afad4db57..0bdd5e64a7f2 100644
--- a/lib/CodeGen/FuncletLayout.cpp
+++ b/lib/CodeGen/FuncletLayout.cpp
@@ -37,7 +37,7 @@ public:
char FuncletLayout::ID = 0;
char &llvm::FuncletLayoutID = FuncletLayout::ID;
-INITIALIZE_PASS(FuncletLayout, "funclet-layout",
+INITIALIZE_PASS(FuncletLayout, DEBUG_TYPE,
"Contiguously Lay Out Funclets", false, false)
bool FuncletLayout::runOnMachineFunction(MachineFunction &F) {
diff --git a/lib/CodeGen/GlobalISel/CMakeLists.txt b/lib/CodeGen/GlobalISel/CMakeLists.txt
index 03a8c4f5f909..eba7ea8132e3 100644
--- a/lib/CodeGen/GlobalISel/CMakeLists.txt
+++ b/lib/CodeGen/GlobalISel/CMakeLists.txt
@@ -8,6 +8,7 @@ set(GLOBAL_ISEL_FILES
LegalizerHelper.cpp
Legalizer.cpp
LegalizerInfo.cpp
+ Localizer.cpp
RegBankSelect.cpp
RegisterBank.cpp
RegisterBankInfo.cpp
@@ -24,11 +25,11 @@ endif()
# In LLVMBuild.txt files, it is not possible to mark a dependency to a
# library as optional. So instead, generate an empty library if we did
-# not ask for it.
+# not ask for it.
add_llvm_library(LLVMGlobalISel
${GLOBAL_ISEL_BUILD_FILES}
GlobalISel.cpp
-
+
DEPENDS
intrinsics_gen
)
diff --git a/lib/CodeGen/GlobalISel/GlobalISel.cpp b/lib/CodeGen/GlobalISel/GlobalISel.cpp
index fcd2722f1c2f..29d1209bb02a 100644
--- a/lib/CodeGen/GlobalISel/GlobalISel.cpp
+++ b/lib/CodeGen/GlobalISel/GlobalISel.cpp
@@ -26,6 +26,7 @@ void llvm::initializeGlobalISel(PassRegistry &Registry) {
void llvm::initializeGlobalISel(PassRegistry &Registry) {
initializeIRTranslatorPass(Registry);
initializeLegalizerPass(Registry);
+ initializeLocalizerPass(Registry);
initializeRegBankSelectPass(Registry);
initializeInstructionSelectPass(Registry);
}
diff --git a/lib/CodeGen/GlobalISel/Localizer.cpp b/lib/CodeGen/GlobalISel/Localizer.cpp
new file mode 100644
index 000000000000..bdca732b4e33
--- /dev/null
+++ b/lib/CodeGen/GlobalISel/Localizer.cpp
@@ -0,0 +1,125 @@
+//===- Localizer.cpp ---------------------- Localize some instrs -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements the Localizer class.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/GlobalISel/Localizer.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "localizer"
+
+using namespace llvm;
+
+char Localizer::ID = 0;
+INITIALIZE_PASS(Localizer, DEBUG_TYPE,
+ "Move/duplicate certain instructions close to their use", false,
+ false);
+
+Localizer::Localizer() : MachineFunctionPass(ID) {
+ initializeLocalizerPass(*PassRegistry::getPassRegistry());
+}
+
+void Localizer::init(MachineFunction &MF) { MRI = &MF.getRegInfo(); }
+
+bool Localizer::shouldLocalize(const MachineInstr &MI) {
+ switch (MI.getOpcode()) {
+ default:
+ return false;
+ // Constants-like instructions should be close to their users.
+ // We don't want long live-ranges for them.
+ case TargetOpcode::G_CONSTANT:
+ case TargetOpcode::G_FCONSTANT:
+ case TargetOpcode::G_FRAME_INDEX:
+ return true;
+ }
+}
+
+bool Localizer::isLocalUse(MachineOperand &MOUse, const MachineInstr &Def,
+ MachineBasicBlock *&InsertMBB) {
+ MachineInstr &MIUse = *MOUse.getParent();
+ InsertMBB = MIUse.getParent();
+ if (MIUse.isPHI())
+ InsertMBB = MIUse.getOperand(MIUse.getOperandNo(&MOUse) + 1).getMBB();
+ return InsertMBB == Def.getParent();
+}
+
+bool Localizer::runOnMachineFunction(MachineFunction &MF) {
+ // If the ISel pipeline failed, do not bother running that pass.
+ if (MF.getProperties().hasProperty(
+ MachineFunctionProperties::Property::FailedISel))
+ return false;
+
+ DEBUG(dbgs() << "Localize instructions for: " << MF.getName() << '\n');
+
+ init(MF);
+
+ bool Changed = false;
+ // Keep track of the instructions we localized.
+ // We won't need to process them if we see them later in the CFG.
+ SmallPtrSet<MachineInstr *, 16> LocalizedInstrs;
+ DenseMap<std::pair<MachineBasicBlock *, unsigned>, unsigned> MBBWithLocalDef;
+ // TODO: Do bottom up traversal.
+ for (MachineBasicBlock &MBB : MF) {
+ for (MachineInstr &MI : MBB) {
+ if (LocalizedInstrs.count(&MI) || !shouldLocalize(MI))
+ continue;
+ DEBUG(dbgs() << "Should localize: " << MI);
+ assert(MI.getDesc().getNumDefs() == 1 &&
+ "More than one definition not supported yet");
+ unsigned Reg = MI.getOperand(0).getReg();
+ // Check if all the users of MI are local.
+ // We are going to invalidation the list of use operands, so we
+ // can't use range iterator.
+ for (auto MOIt = MRI->use_begin(Reg), MOItEnd = MRI->use_end();
+ MOIt != MOItEnd;) {
+ MachineOperand &MOUse = *MOIt++;
+ // Check if the use is already local.
+ MachineBasicBlock *InsertMBB;
+ DEBUG(MachineInstr &MIUse = *MOUse.getParent();
+ dbgs() << "Checking use: " << MIUse
+ << " #Opd: " << MIUse.getOperandNo(&MOUse) << '\n');
+ if (isLocalUse(MOUse, MI, InsertMBB))
+ continue;
+ DEBUG(dbgs() << "Fixing non-local use\n");
+ Changed = true;
+ auto MBBAndReg = std::make_pair(InsertMBB, Reg);
+ auto NewVRegIt = MBBWithLocalDef.find(MBBAndReg);
+ if (NewVRegIt == MBBWithLocalDef.end()) {
+ // Create the localized instruction.
+ MachineInstr *LocalizedMI = MF.CloneMachineInstr(&MI);
+ LocalizedInstrs.insert(LocalizedMI);
+ // Move it at the right place.
+ MachineInstr &MIUse = *MOUse.getParent();
+ if (MIUse.getParent() == InsertMBB)
+ InsertMBB->insert(MIUse, LocalizedMI);
+ else
+ InsertMBB->insert(InsertMBB->getFirstNonPHI(), LocalizedMI);
+
+ // Set a new register for the definition.
+ unsigned NewReg =
+ MRI->createGenericVirtualRegister(MRI->getType(Reg));
+ MRI->setRegClassOrRegBank(NewReg, MRI->getRegClassOrRegBank(Reg));
+ LocalizedMI->getOperand(0).setReg(NewReg);
+ NewVRegIt =
+ MBBWithLocalDef.insert(std::make_pair(MBBAndReg, NewReg)).first;
+ DEBUG(dbgs() << "Inserted: " << *LocalizedMI);
+ }
+ DEBUG(dbgs() << "Update use with: " << PrintReg(NewVRegIt->second)
+ << '\n');
+ // Update the user reg.
+ MOUse.setReg(NewVRegIt->second);
+ }
+ }
+ }
+ return Changed;
+}
diff --git a/lib/CodeGen/GlobalMerge.cpp b/lib/CodeGen/GlobalMerge.cpp
index 1ea534939948..23812a2a2344 100644
--- a/lib/CodeGen/GlobalMerge.cpp
+++ b/lib/CodeGen/GlobalMerge.cpp
@@ -192,10 +192,7 @@ namespace {
} // end anonymous namespace
char GlobalMerge::ID = 0;
-INITIALIZE_PASS_BEGIN(GlobalMerge, "global-merge", "Merge global variables",
- false, false)
-INITIALIZE_PASS_END(GlobalMerge, "global-merge", "Merge global variables",
- false, false)
+INITIALIZE_PASS(GlobalMerge, DEBUG_TYPE, "Merge global variables", false, false)
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals,
Module &M, bool isConst, unsigned AddrSpace) const {
diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp
index 628d599a3cc7..1c33f3b6800e 100644
--- a/lib/CodeGen/IfConversion.cpp
+++ b/lib/CodeGen/IfConversion.cpp
@@ -39,7 +39,7 @@
using namespace llvm;
-#define DEBUG_TYPE "ifcvt"
+#define DEBUG_TYPE "if-converter"
// Hidden options for help debugging.
static cl::opt<int> IfCvtFnStart("ifcvt-fn-start", cl::init(-1), cl::Hidden);
@@ -316,9 +316,9 @@ namespace {
char &llvm::IfConverterID = IfConverter::ID;
-INITIALIZE_PASS_BEGIN(IfConverter, "if-converter", "If Converter", false, false)
+INITIALIZE_PASS_BEGIN(IfConverter, DEBUG_TYPE, "If Converter", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
-INITIALIZE_PASS_END(IfConverter, "if-converter", "If Converter", false, false)
+INITIALIZE_PASS_END(IfConverter, DEBUG_TYPE, "If Converter", false, false)
bool IfConverter::runOnMachineFunction(MachineFunction &MF) {
if (skipFunction(*MF.getFunction()) || (PredicateFtor && !PredicateFtor(MF)))
@@ -1588,32 +1588,22 @@ bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) {
BBCvt = MBPI->getEdgeProbability(BBI.BB, &CvtMBB);
}
- // To be able to insert code freely at the end of BBI we sometimes remove
- // the branch from BBI to NextMBB temporarily. Remember if this happened.
- bool RemovedBranchToNextMBB = false;
if (CvtMBB.pred_size() > 1) {
BBI.NonPredSize -= TII->removeBranch(*BBI.BB);
// Copy instructions in the true block, predicate them, and add them to
// the entry block.
CopyAndPredicateBlock(BBI, *CvtBBI, Cond, true);
- // Keep the CFG updated.
+ // RemoveExtraEdges won't work if the block has an unanalyzable branch, so
+ // explicitly remove CvtBBI as a successor.
BBI.BB->removeSuccessor(&CvtMBB, true);
} else {
// Predicate the 'true' block after removing its branch.
CvtBBI->NonPredSize -= TII->removeBranch(CvtMBB);
PredicateBlock(*CvtBBI, CvtMBB.end(), Cond);
- // Remove the branch from the entry of the triangle to NextBB to be able to
- // do the merge below. Keep the CFG updated, but remember we removed the
- // branch since we do want to execute NextMBB, either by introducing a
- // branch to it again, or merging it into the entry block.
- // How it's handled is decided further down.
- BBI.NonPredSize -= TII->removeBranch(*BBI.BB);
- BBI.BB->removeSuccessor(&NextMBB, true);
- RemovedBranchToNextMBB = true;
-
// Now merge the entry of the triangle with the true block.
+ BBI.NonPredSize -= TII->removeBranch(*BBI.BB);
MergeBlocks(BBI, *CvtBBI, false);
}
@@ -1651,19 +1641,12 @@ bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) {
// block. By not merging them, we make it possible to iteratively
// ifcvt the blocks.
if (!HasEarlyExit &&
- // We might have removed BBI from NextMBB's predecessor list above but
- // we want it to be there, so consider that too.
- (NextMBB.pred_size() == (RemovedBranchToNextMBB ? 0 : 1)) &&
- !NextBBI->HasFallThrough &&
+ NextMBB.pred_size() == 1 && !NextBBI->HasFallThrough &&
!NextMBB.hasAddressTaken()) {
- // We will merge NextBBI into BBI, and thus remove the current
- // fallthrough from BBI into CvtBBI.
- BBI.BB->removeSuccessor(&CvtMBB, true);
MergeBlocks(BBI, *NextBBI);
FalseBBDead = true;
} else {
InsertUncondBranch(*BBI.BB, NextMBB, TII);
- BBI.BB->addSuccessor(&NextMBB);
BBI.HasFallThrough = false;
}
// Mixed predicated and unpredicated code. This cannot be iteratively
@@ -1671,6 +1654,8 @@ bool IfConverter::IfConvertTriangle(BBInfo &BBI, IfcvtKind Kind) {
IterIfcvt = false;
}
+ RemoveExtraEdges(BBI);
+
// Update block info. BB can be iteratively if-converted.
if (!IterIfcvt)
BBI.IsDone = true;
diff --git a/lib/CodeGen/ImplicitNullChecks.cpp b/lib/CodeGen/ImplicitNullChecks.cpp
index 920c2a372a9b..24e289dd4f1b 100644
--- a/lib/CodeGen/ImplicitNullChecks.cpp
+++ b/lib/CodeGen/ImplicitNullChecks.cpp
@@ -674,8 +674,8 @@ void ImplicitNullChecks::rewriteNullChecks(
char ImplicitNullChecks::ID = 0;
char &llvm::ImplicitNullChecksID = ImplicitNullChecks::ID;
-INITIALIZE_PASS_BEGIN(ImplicitNullChecks, "implicit-null-checks",
+INITIALIZE_PASS_BEGIN(ImplicitNullChecks, DEBUG_TYPE,
"Implicit null checks", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
-INITIALIZE_PASS_END(ImplicitNullChecks, "implicit-null-checks",
+INITIALIZE_PASS_END(ImplicitNullChecks, DEBUG_TYPE,
"Implicit null checks", false, false)
diff --git a/lib/CodeGen/InterleavedAccessPass.cpp b/lib/CodeGen/InterleavedAccessPass.cpp
index bb29db301a95..ee4929c91482 100644
--- a/lib/CodeGen/InterleavedAccessPass.cpp
+++ b/lib/CodeGen/InterleavedAccessPass.cpp
@@ -107,13 +107,11 @@ private:
} // end anonymous namespace.
char InterleavedAccess::ID = 0;
-INITIALIZE_PASS_BEGIN(
- InterleavedAccess, "interleaved-access",
+INITIALIZE_PASS_BEGIN(InterleavedAccess, DEBUG_TYPE,
"Lower interleaved memory accesses to target specific intrinsics", false,
false)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
-INITIALIZE_PASS_END(
- InterleavedAccess, "interleaved-access",
+INITIALIZE_PASS_END(InterleavedAccess, DEBUG_TYPE,
"Lower interleaved memory accesses to target specific intrinsics", false,
false)
diff --git a/lib/CodeGen/LexicalScopes.cpp b/lib/CodeGen/LexicalScopes.cpp
index 275d84e2c185..40ee7ea785f0 100644
--- a/lib/CodeGen/LexicalScopes.cpp
+++ b/lib/CodeGen/LexicalScopes.cpp
@@ -86,8 +86,9 @@ void LexicalScopes::extractLexicalScopes(
continue;
}
- // Ignore DBG_VALUE. It does not contribute to any instruction in output.
- if (MInsn.isDebugValue())
+ // Ignore DBG_VALUE and similar instruction that do not contribute to any
+ // instruction in the output.
+ if (MInsn.isMetaInstruction())
continue;
if (RangeBeginMI) {
diff --git a/lib/CodeGen/LiveDebugValues.cpp b/lib/CodeGen/LiveDebugValues.cpp
index f956974b1aaf..b5e705f6455d 100644
--- a/lib/CodeGen/LiveDebugValues.cpp
+++ b/lib/CodeGen/LiveDebugValues.cpp
@@ -43,7 +43,7 @@
using namespace llvm;
-#define DEBUG_TYPE "live-debug-values"
+#define DEBUG_TYPE "livedebugvalues"
STATISTIC(NumInserted, "Number of DBG_VALUE instructions inserted");
@@ -283,7 +283,7 @@ public:
char LiveDebugValues::ID = 0;
char &llvm::LiveDebugValuesID = LiveDebugValues::ID;
-INITIALIZE_PASS(LiveDebugValues, "livedebugvalues", "Live DEBUG_VALUE analysis",
+INITIALIZE_PASS(LiveDebugValues, DEBUG_TYPE, "Live DEBUG_VALUE analysis",
false, false)
/// Default construct and initialize the pass.
diff --git a/lib/CodeGen/LiveDebugVariables.cpp b/lib/CodeGen/LiveDebugVariables.cpp
index bcf7c8e99c7f..bbd783367c9e 100644
--- a/lib/CodeGen/LiveDebugVariables.cpp
+++ b/lib/CodeGen/LiveDebugVariables.cpp
@@ -45,7 +45,7 @@
using namespace llvm;
-#define DEBUG_TYPE "livedebug"
+#define DEBUG_TYPE "livedebugvars"
static cl::opt<bool>
EnableLDV("live-debug-variables", cl::init(true),
@@ -54,11 +54,11 @@ EnableLDV("live-debug-variables", cl::init(true),
STATISTIC(NumInsertedDebugValues, "Number of DBG_VALUEs inserted");
char LiveDebugVariables::ID = 0;
-INITIALIZE_PASS_BEGIN(LiveDebugVariables, "livedebugvars",
+INITIALIZE_PASS_BEGIN(LiveDebugVariables, DEBUG_TYPE,
"Debug Variable Analysis", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
-INITIALIZE_PASS_END(LiveDebugVariables, "livedebugvars",
+INITIALIZE_PASS_END(LiveDebugVariables, DEBUG_TYPE,
"Debug Variable Analysis", false, false)
void LiveDebugVariables::getAnalysisUsage(AnalysisUsage &AU) const {
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index 3f5b8e19d1f0..0c05dbeacba0 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -1,4 +1,4 @@
-//===-- LiveIntervalAnalysis.cpp - Live Interval Analysis -----------------===//
+//===- LiveIntervalAnalysis.cpp - Live Interval Analysis ------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -14,28 +14,45 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "LiveRangeCalc.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/CodeGen/LiveInterval.h"
+#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/LiveVariables.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
+#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
+#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/VirtRegMap.h"
-#include "llvm/IR/Value.h"
+#include "llvm/MC/LaneBitmask.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <algorithm>
-#include <cmath>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <tuple>
+#include <utility>
+
using namespace llvm;
#define DEBUG_TYPE "regalloc"
@@ -59,11 +76,13 @@ static bool EnablePrecomputePhysRegs = false;
#endif // NDEBUG
namespace llvm {
+
cl::opt<bool> UseSegmentSetForPhysRegs(
"use-segment-set-for-physregs", cl::Hidden, cl::init(true),
cl::desc(
"Use segment set for the computation of the live ranges of physregs."));
-}
+
+} // end namespace llvm
void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
@@ -78,8 +97,7 @@ void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const {
MachineFunctionPass::getAnalysisUsage(AU);
}
-LiveIntervals::LiveIntervals() : MachineFunctionPass(ID),
- DomTree(nullptr), LRCalc(nullptr) {
+LiveIntervals::LiveIntervals() : MachineFunctionPass(ID) {
initializeLiveIntervalsPass(*PassRegistry::getPassRegistry());
}
@@ -168,12 +186,10 @@ LLVM_DUMP_METHOD void LiveIntervals::dumpInstrs() const {
#endif
LiveInterval* LiveIntervals::createInterval(unsigned reg) {
- float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ?
- llvm::huge_valf : 0.0F;
+ float Weight = TargetRegisterInfo::isPhysicalRegister(reg) ? huge_valf : 0.0F;
return new LiveInterval(reg, Weight);
}
-
/// Compute the live interval of a virtual register, based on defs and uses.
void LiveIntervals::computeVirtRegInterval(LiveInterval &LI) {
assert(LRCalc && "LRCalc not initialized.");
@@ -337,7 +353,7 @@ static void createSegmentsForValues(LiveRange &LR,
}
}
-typedef SmallVector<std::pair<SlotIndex, VNInfo*>, 16> ShrinkToUsesWorkList;
+using ShrinkToUsesWorkList = SmallVector<std::pair<SlotIndex, VNInfo*>, 16>;
static void extendSegmentsToUses(LiveRange &LR, const SlotIndexes &Indexes,
ShrinkToUsesWorkList &WorkList,
@@ -593,7 +609,7 @@ void LiveIntervals::pruneValue(LiveRange &LR, SlotIndex Kill,
// Find all blocks that are reachable from KillMBB without leaving VNI's live
// range. It is possible that KillMBB itself is reachable, so start a DFS
// from each successor.
- typedef df_iterator_default_set<MachineBasicBlock*,9> VisitedTy;
+ using VisitedTy = df_iterator_default_set<MachineBasicBlock*,9>;
VisitedTy Visited;
for (MachineBasicBlock *Succ : KillMBB->successors()) {
for (df_ext_iterator<MachineBasicBlock*, VisitedTy>
@@ -822,7 +838,6 @@ LiveIntervals::addSegmentToEndOfBlock(unsigned reg, MachineInstr &startInst) {
return S;
}
-
//===----------------------------------------------------------------------===//
// Register mask functions
//===----------------------------------------------------------------------===//
@@ -855,7 +870,7 @@ bool LiveIntervals::checkRegMaskInterference(LiveInterval &LI,
return false;
bool Found = false;
- for (;;) {
+ while (true) {
assert(*SlotI >= LiveI->start);
// Loop over all slots overlapping this segment.
while (*SlotI < LiveI->end) {
diff --git a/lib/CodeGen/LivePhysRegs.cpp b/lib/CodeGen/LivePhysRegs.cpp
index 9f7d7cf54848..0dc1079b2ad4 100644
--- a/lib/CodeGen/LivePhysRegs.cpp
+++ b/lib/CodeGen/LivePhysRegs.cpp
@@ -53,7 +53,7 @@ void LivePhysRegs::stepBackward(const MachineInstr &MI) {
continue;
removeReg(Reg);
} else if (O->isRegMask())
- removeRegsInMask(*O, nullptr);
+ removeRegsInMask(*O);
}
// Add uses to the set.
@@ -142,66 +142,85 @@ bool LivePhysRegs::available(const MachineRegisterInfo &MRI,
/// Add live-in registers of basic block \p MBB to \p LiveRegs.
void LivePhysRegs::addBlockLiveIns(const MachineBasicBlock &MBB) {
for (const auto &LI : MBB.liveins()) {
- MCSubRegIndexIterator S(LI.PhysReg, TRI);
- if (LI.LaneMask.all() || (LI.LaneMask.any() && !S.isValid())) {
- addReg(LI.PhysReg);
+ unsigned Reg = LI.PhysReg;
+ LaneBitmask Mask = LI.LaneMask;
+ MCSubRegIndexIterator S(Reg, TRI);
+ assert(Mask.any() && "Invalid livein mask");
+ if (Mask.all() || !S.isValid()) {
+ addReg(Reg);
continue;
}
for (; S.isValid(); ++S) {
unsigned SI = S.getSubRegIndex();
- if ((LI.LaneMask & TRI->getSubRegIndexLaneMask(SI)).any())
+ if ((Mask & TRI->getSubRegIndexLaneMask(SI)).any())
addReg(S.getSubReg());
}
}
}
-/// Add pristine registers to the given \p LiveRegs. This function removes
-/// actually saved callee save registers when \p InPrologueEpilogue is false.
-static void addPristines(LivePhysRegs &LiveRegs, const MachineFunction &MF,
- const MachineFrameInfo &MFI,
- const TargetRegisterInfo &TRI) {
+/// Adds all callee saved registers to \p LiveRegs.
+static void addCalleeSavedRegs(LivePhysRegs &LiveRegs,
+ const MachineFunction &MF) {
const MachineRegisterInfo &MRI = MF.getRegInfo();
- for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR;
- ++CSR)
+ for (const MCPhysReg *CSR = MRI.getCalleeSavedRegs(); CSR && *CSR; ++CSR)
LiveRegs.addReg(*CSR);
+}
+
+/// Adds pristine registers to the given \p LiveRegs. Pristine registers are
+/// callee saved registers that are unused in the function.
+static void addPristines(LivePhysRegs &LiveRegs, const MachineFunction &MF) {
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ if (!MFI.isCalleeSavedInfoValid())
+ return;
+ /// Add all callee saved regs, then remove the ones that are saved+restored.
+ addCalleeSavedRegs(LiveRegs, MF);
+ /// Remove the ones that are not saved/restored; they are pristine.
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())
LiveRegs.removeReg(Info.getReg());
}
void LivePhysRegs::addLiveOutsNoPristines(const MachineBasicBlock &MBB) {
- // To get the live-outs we simply merge the live-ins of all successors.
- for (const MachineBasicBlock *Succ : MBB.successors())
- addBlockLiveIns(*Succ);
+ if (!MBB.succ_empty()) {
+ // To get the live-outs we simply merge the live-ins of all successors.
+ for (const MachineBasicBlock *Succ : MBB.successors())
+ addBlockLiveIns(*Succ);
+ } else if (MBB.isReturnBlock()) {
+ // For the return block: Add all callee saved registers that are saved and
+ // restored (somewhere); This does not include callee saved registers that
+ // are unused and hence not saved and restored; they are called pristine.
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ if (MFI.isCalleeSavedInfoValid()) {
+ for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())
+ addReg(Info.getReg());
+ }
+ }
}
void LivePhysRegs::addLiveOuts(const MachineBasicBlock &MBB) {
- const MachineFunction &MF = *MBB.getParent();
- const MachineFrameInfo &MFI = MF.getFrameInfo();
- if (MFI.isCalleeSavedInfoValid()) {
- if (MBB.isReturnBlock()) {
- // The return block has no successors whose live-ins we could merge
- // below. So instead we add the callee saved registers manually.
- const MachineRegisterInfo &MRI = MF.getRegInfo();
- for (const MCPhysReg *I = MRI.getCalleeSavedRegs(); *I; ++I)
- addReg(*I);
- } else {
- addPristines(*this, MF, MFI, *TRI);
- }
+ if (!MBB.succ_empty()) {
+ const MachineFunction &MF = *MBB.getParent();
+ addPristines(*this, MF);
+ addLiveOutsNoPristines(MBB);
+ } else if (MBB.isReturnBlock()) {
+ // For the return block: Add all callee saved registers.
+ const MachineFunction &MF = *MBB.getParent();
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ if (MFI.isCalleeSavedInfoValid())
+ addCalleeSavedRegs(*this, MF);
}
-
- addLiveOutsNoPristines(MBB);
}
void LivePhysRegs::addLiveIns(const MachineBasicBlock &MBB) {
const MachineFunction &MF = *MBB.getParent();
- const MachineFrameInfo &MFI = MF.getFrameInfo();
- if (MFI.isCalleeSavedInfoValid())
- addPristines(*this, MF, MFI, *TRI);
+ addPristines(*this, MF);
addBlockLiveIns(MBB);
}
-void llvm::computeLiveIns(LivePhysRegs &LiveRegs, const TargetRegisterInfo &TRI,
+void llvm::computeLiveIns(LivePhysRegs &LiveRegs,
+ const MachineRegisterInfo &MRI,
MachineBasicBlock &MBB) {
+ const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
assert(MBB.livein_empty());
LiveRegs.init(TRI);
LiveRegs.addLiveOutsNoPristines(MBB);
@@ -209,10 +228,12 @@ void llvm::computeLiveIns(LivePhysRegs &LiveRegs, const TargetRegisterInfo &TRI,
LiveRegs.stepBackward(MI);
for (unsigned Reg : LiveRegs) {
+ if (MRI.isReserved(Reg))
+ continue;
// Skip the register if we are about to add one of its super registers.
bool ContainsSuperReg = false;
for (MCSuperRegIterator SReg(Reg, &TRI); SReg.isValid(); ++SReg) {
- if (LiveRegs.contains(*SReg)) {
+ if (LiveRegs.contains(*SReg) && !MRI.isReserved(*SReg)) {
ContainsSuperReg = true;
break;
}
diff --git a/lib/CodeGen/LiveStackAnalysis.cpp b/lib/CodeGen/LiveStackAnalysis.cpp
index dbf1f96102d1..b51f8b0aa6bb 100644
--- a/lib/CodeGen/LiveStackAnalysis.cpp
+++ b/lib/CodeGen/LiveStackAnalysis.cpp
@@ -25,10 +25,10 @@ using namespace llvm;
#define DEBUG_TYPE "livestacks"
char LiveStacks::ID = 0;
-INITIALIZE_PASS_BEGIN(LiveStacks, "livestacks",
+INITIALIZE_PASS_BEGIN(LiveStacks, DEBUG_TYPE,
"Live Stack Slot Analysis", false, false)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
-INITIALIZE_PASS_END(LiveStacks, "livestacks",
+INITIALIZE_PASS_END(LiveStacks, DEBUG_TYPE,
"Live Stack Slot Analysis", false, false)
char &llvm::LiveStacksID = LiveStacks::ID;
diff --git a/lib/CodeGen/LocalStackSlotAllocation.cpp b/lib/CodeGen/LocalStackSlotAllocation.cpp
index e189fb0dd89d..17cab0ae910e 100644
--- a/lib/CodeGen/LocalStackSlotAllocation.cpp
+++ b/lib/CodeGen/LocalStackSlotAllocation.cpp
@@ -103,10 +103,10 @@ namespace {
char LocalStackSlotPass::ID = 0;
char &llvm::LocalStackSlotAllocationID = LocalStackSlotPass::ID;
-INITIALIZE_PASS_BEGIN(LocalStackSlotPass, "localstackalloc",
+INITIALIZE_PASS_BEGIN(LocalStackSlotPass, DEBUG_TYPE,
"Local Stack Slot Allocation", false, false)
INITIALIZE_PASS_DEPENDENCY(StackProtector)
-INITIALIZE_PASS_END(LocalStackSlotPass, "localstackalloc",
+INITIALIZE_PASS_END(LocalStackSlotPass, DEBUG_TYPE,
"Local Stack Slot Allocation", false, false)
diff --git a/lib/CodeGen/LowerEmuTLS.cpp b/lib/CodeGen/LowerEmuTLS.cpp
index 5fb5b747f471..0fc48d4e0b6b 100644
--- a/lib/CodeGen/LowerEmuTLS.cpp
+++ b/lib/CodeGen/LowerEmuTLS.cpp
@@ -53,7 +53,7 @@ private:
char LowerEmuTLS::ID = 0;
-INITIALIZE_PASS(LowerEmuTLS, "loweremutls",
+INITIALIZE_PASS(LowerEmuTLS, DEBUG_TYPE,
"Add __emutls_[vt]. variables for emultated TLS model", false,
false)
diff --git a/lib/CodeGen/MachineBlockFrequencyInfo.cpp b/lib/CodeGen/MachineBlockFrequencyInfo.cpp
index 9c7367b4c780..4d1ec11df46c 100644
--- a/lib/CodeGen/MachineBlockFrequencyInfo.cpp
+++ b/lib/CodeGen/MachineBlockFrequencyInfo.cpp
@@ -26,7 +26,7 @@
using namespace llvm;
-#define DEBUG_TYPE "block-freq"
+#define DEBUG_TYPE "machine-block-freq"
static cl::opt<GVDAGType> ViewMachineBlockFreqPropagationDAG(
@@ -149,11 +149,11 @@ struct DOTGraphTraits<MachineBlockFrequencyInfo *>
} // end namespace llvm
-INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, "machine-block-freq",
+INITIALIZE_PASS_BEGIN(MachineBlockFrequencyInfo, DEBUG_TYPE,
"Machine Block Frequency Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
-INITIALIZE_PASS_END(MachineBlockFrequencyInfo, "machine-block-freq",
+INITIALIZE_PASS_END(MachineBlockFrequencyInfo, DEBUG_TYPE,
"Machine Block Frequency Analysis", true, true)
char MachineBlockFrequencyInfo::ID = 0;
diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp
index adfca9a46239..c1ca8e8e83b4 100644
--- a/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/lib/CodeGen/MachineBlockPlacement.cpp
@@ -499,13 +499,13 @@ public:
char MachineBlockPlacement::ID = 0;
char &llvm::MachineBlockPlacementID = MachineBlockPlacement::ID;
-INITIALIZE_PASS_BEGIN(MachineBlockPlacement, "block-placement",
+INITIALIZE_PASS_BEGIN(MachineBlockPlacement, DEBUG_TYPE,
"Branch Probability Basic Block Placement", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo)
INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
-INITIALIZE_PASS_END(MachineBlockPlacement, "block-placement",
+INITIALIZE_PASS_END(MachineBlockPlacement, DEBUG_TYPE,
"Branch Probability Basic Block Placement", false, false)
#ifndef NDEBUG
diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp
index 0766f465456c..34f6bbd59e9b 100644
--- a/lib/CodeGen/MachineCSE.cpp
+++ b/lib/CodeGen/MachineCSE.cpp
@@ -108,12 +108,12 @@ namespace {
char MachineCSE::ID = 0;
char &llvm::MachineCSEID = MachineCSE::ID;
-INITIALIZE_PASS_BEGIN(MachineCSE, "machine-cse",
- "Machine Common Subexpression Elimination", false, false)
+INITIALIZE_PASS_BEGIN(MachineCSE, DEBUG_TYPE,
+ "Machine Common Subexpression Elimination", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
-INITIALIZE_PASS_END(MachineCSE, "machine-cse",
- "Machine Common Subexpression Elimination", false, false)
+INITIALIZE_PASS_END(MachineCSE, DEBUG_TYPE,
+ "Machine Common Subexpression Elimination", false, false)
/// The source register of a COPY machine instruction can be propagated to all
/// its users, and this propagation could increase the probability of finding
@@ -180,8 +180,8 @@ MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
I = skipDebugInstructionsForward(I, E);
if (I == E)
- // Reached end of block, register is obviously dead.
- return true;
+ // Reached end of block, we don't know if register is dead or not.
+ return false;
bool SeenDef = false;
for (const MachineOperand &MO : I->operands()) {
diff --git a/lib/CodeGen/MachineCombiner.cpp b/lib/CodeGen/MachineCombiner.cpp
index 50e453e4067c..c176de16b593 100644
--- a/lib/CodeGen/MachineCombiner.cpp
+++ b/lib/CodeGen/MachineCombiner.cpp
@@ -86,11 +86,11 @@ private:
char MachineCombiner::ID = 0;
char &llvm::MachineCombinerID = MachineCombiner::ID;
-INITIALIZE_PASS_BEGIN(MachineCombiner, "machine-combiner",
+INITIALIZE_PASS_BEGIN(MachineCombiner, DEBUG_TYPE,
"Machine InstCombiner", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(MachineTraceMetrics)
-INITIALIZE_PASS_END(MachineCombiner, "machine-combiner", "Machine InstCombiner",
+INITIALIZE_PASS_END(MachineCombiner, DEBUG_TYPE, "Machine InstCombiner",
false, false)
void MachineCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
diff --git a/lib/CodeGen/MachineCopyPropagation.cpp b/lib/CodeGen/MachineCopyPropagation.cpp
index 7312dc5e94bd..f83b5481e0a5 100644
--- a/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/lib/CodeGen/MachineCopyPropagation.cpp
@@ -27,7 +27,7 @@
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
-#define DEBUG_TYPE "codegen-cp"
+#define DEBUG_TYPE "machine-cp"
STATISTIC(NumDeletes, "Number of dead copies deleted");
@@ -79,7 +79,7 @@ namespace {
char MachineCopyPropagation::ID = 0;
char &llvm::MachineCopyPropagationID = MachineCopyPropagation::ID;
-INITIALIZE_PASS(MachineCopyPropagation, "machine-cp",
+INITIALIZE_PASS(MachineCopyPropagation, DEBUG_TYPE,
"Machine Copy Propagation Pass", false, false)
/// Remove any entry in \p Map where the register is a subregister or equal to
diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp
index 7eb991744f01..95c62d820b0e 100644
--- a/lib/CodeGen/MachineLICM.cpp
+++ b/lib/CodeGen/MachineLICM.cpp
@@ -38,7 +38,7 @@
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
-#define DEBUG_TYPE "machine-licm"
+#define DEBUG_TYPE "machinelicm"
static cl::opt<bool>
AvoidSpeculation("avoid-speculation",
@@ -237,13 +237,13 @@ namespace {
char MachineLICM::ID = 0;
char &llvm::MachineLICMID = MachineLICM::ID;
-INITIALIZE_PASS_BEGIN(MachineLICM, "machinelicm",
- "Machine Loop Invariant Code Motion", false, false)
+INITIALIZE_PASS_BEGIN(MachineLICM, DEBUG_TYPE,
+ "Machine Loop Invariant Code Motion", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
-INITIALIZE_PASS_END(MachineLICM, "machinelicm",
- "Machine Loop Invariant Code Motion", false, false)
+INITIALIZE_PASS_END(MachineLICM, DEBUG_TYPE,
+ "Machine Loop Invariant Code Motion", false, false)
/// Test if the given loop is the outer-most loop that has a unique predecessor.
static bool LoopIsOuterMostWithPredecessor(MachineLoop *CurLoop) {
diff --git a/lib/CodeGen/MachineOutliner.cpp b/lib/CodeGen/MachineOutliner.cpp
index 581a8ad81149..9ea3c00a2fc4 100644
--- a/lib/CodeGen/MachineOutliner.cpp
+++ b/lib/CodeGen/MachineOutliner.cpp
@@ -901,7 +901,7 @@ namespace llvm {
ModulePass *createMachineOutlinerPass() { return new MachineOutliner(); }
}
-INITIALIZE_PASS(MachineOutliner, "machine-outliner",
+INITIALIZE_PASS(MachineOutliner, DEBUG_TYPE,
"Machine Function Outliner", false, false)
void MachineOutliner::pruneOverlaps(std::vector<Candidate> &CandidateList,
diff --git a/lib/CodeGen/MachinePipeliner.cpp b/lib/CodeGen/MachinePipeliner.cpp
index d06c38cf4ed8..8f5ac8b3fc45 100644
--- a/lib/CodeGen/MachinePipeliner.cpp
+++ b/lib/CodeGen/MachinePipeliner.cpp
@@ -715,13 +715,13 @@ char MachinePipeliner::ID = 0;
int MachinePipeliner::NumTries = 0;
#endif
char &llvm::MachinePipelinerID = MachinePipeliner::ID;
-INITIALIZE_PASS_BEGIN(MachinePipeliner, "pipeliner",
+INITIALIZE_PASS_BEGIN(MachinePipeliner, DEBUG_TYPE,
"Modulo Software Pipelining", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
-INITIALIZE_PASS_END(MachinePipeliner, "pipeliner",
+INITIALIZE_PASS_END(MachinePipeliner, DEBUG_TYPE,
"Modulo Software Pipelining", false, false)
/// The "main" function for implementing Swing Modulo Scheduling.
diff --git a/lib/CodeGen/MachineScheduler.cpp b/lib/CodeGen/MachineScheduler.cpp
index 41e161f71e53..edc3783afa2f 100644
--- a/lib/CodeGen/MachineScheduler.cpp
+++ b/lib/CodeGen/MachineScheduler.cpp
@@ -69,7 +69,7 @@
using namespace llvm;
-#define DEBUG_TYPE "misched"
+#define DEBUG_TYPE "machine-scheduler"
namespace llvm {
@@ -191,13 +191,13 @@ char MachineScheduler::ID = 0;
char &llvm::MachineSchedulerID = MachineScheduler::ID;
-INITIALIZE_PASS_BEGIN(MachineScheduler, "machine-scheduler",
+INITIALIZE_PASS_BEGIN(MachineScheduler, DEBUG_TYPE,
"Machine Instruction Scheduler", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
-INITIALIZE_PASS_END(MachineScheduler, "machine-scheduler",
+INITIALIZE_PASS_END(MachineScheduler, DEBUG_TYPE,
"Machine Instruction Scheduler", false, false)
MachineScheduler::MachineScheduler()
@@ -532,7 +532,7 @@ void MachineSchedulerBase::scheduleRegions(ScheduleDAGInstrs &Scheduler,
// thumb2 size reduction is currently an exception, so the PostMIScheduler
// needs to do this.
if (FixKillFlags)
- Scheduler.fixupKills(&*MBB);
+ Scheduler.fixupKills(*MBB);
}
Scheduler.finalizeSchedule();
}
@@ -3233,6 +3233,12 @@ void PostGenericScheduler::tryCandidate(SchedCandidate &Cand,
Top.getLatencyStallCycles(Cand.SU), TryCand, Cand, Stall))
return;
+ // Keep clustered nodes together.
+ if (tryGreater(TryCand.SU == DAG->getNextClusterSucc(),
+ Cand.SU == DAG->getNextClusterSucc(),
+ TryCand, Cand, Cluster))
+ return;
+
// Avoid critical resource consumption and balance the schedule.
if (tryLess(TryCand.ResDelta.CritResources, Cand.ResDelta.CritResources,
TryCand, Cand, ResourceReduce))
diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp
index 5f87b68123f1..7c34e71a0cce 100644
--- a/lib/CodeGen/MachineSink.cpp
+++ b/lib/CodeGen/MachineSink.cpp
@@ -173,14 +173,14 @@ namespace {
char MachineSinking::ID = 0;
char &llvm::MachineSinkingID = MachineSinking::ID;
-INITIALIZE_PASS_BEGIN(MachineSinking, "machine-sink",
- "Machine code sinking", false, false)
+INITIALIZE_PASS_BEGIN(MachineSinking, DEBUG_TYPE,
+ "Machine code sinking", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
-INITIALIZE_PASS_END(MachineSinking, "machine-sink",
- "Machine code sinking", false, false)
+INITIALIZE_PASS_END(MachineSinking, DEBUG_TYPE,
+ "Machine code sinking", false, false)
bool MachineSinking::PerformTrivialForwardCoalescing(MachineInstr &MI,
MachineBasicBlock *MBB) {
diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp
index 998a9645e68b..01391a1a0e50 100644
--- a/lib/CodeGen/MachineTraceMetrics.cpp
+++ b/lib/CodeGen/MachineTraceMetrics.cpp
@@ -44,12 +44,12 @@ using namespace llvm;
char MachineTraceMetrics::ID = 0;
char &llvm::MachineTraceMetricsID = MachineTraceMetrics::ID;
-INITIALIZE_PASS_BEGIN(MachineTraceMetrics,
- "machine-trace-metrics", "Machine Trace Metrics", false, true)
+INITIALIZE_PASS_BEGIN(MachineTraceMetrics, DEBUG_TYPE,
+ "Machine Trace Metrics", false, true)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
-INITIALIZE_PASS_END(MachineTraceMetrics,
- "machine-trace-metrics", "Machine Trace Metrics", false, true)
+INITIALIZE_PASS_END(MachineTraceMetrics, DEBUG_TYPE,
+ "Machine Trace Metrics", false, true)
MachineTraceMetrics::MachineTraceMetrics() : MachineFunctionPass(ID) {
std::fill(std::begin(Ensembles), std::end(Ensembles), nullptr);
diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp
index b53b002f55a6..265f93c363ca 100644
--- a/lib/CodeGen/MachineVerifier.cpp
+++ b/lib/CodeGen/MachineVerifier.cpp
@@ -87,7 +87,6 @@ namespace {
RegSet regsLive;
RegVector regsDefined, regsDead, regsKilled;
RegMaskVector regMasks;
- RegSet regsLiveInButUnused;
SlotIndex lastIndex;
@@ -419,7 +418,6 @@ unsigned MachineVerifier::verify(MachineFunction &MF) {
regsDead.clear();
regsKilled.clear();
regMasks.clear();
- regsLiveInButUnused.clear();
MBBInfoMap.clear();
return foundErrors;
@@ -756,7 +754,6 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
regsLive.insert(*SubRegs);
}
}
- regsLiveInButUnused = regsLive;
const MachineFrameInfo &MFI = MF->getFrameInfo();
BitVector PR = MFI.getPristineRegs(*MF);
@@ -1268,8 +1265,6 @@ void MachineVerifier::checkLiveness(const MachineOperand *MO, unsigned MONum) {
// Both use and def operands can read a register.
if (MO->readsReg()) {
- regsLiveInButUnused.erase(Reg);
-
if (MO->isKill())
addRegWithSubRegs(regsKilled, Reg);
diff --git a/lib/CodeGen/OptimizePHIs.cpp b/lib/CodeGen/OptimizePHIs.cpp
index 2a8531f337a0..76ad668104b4 100644
--- a/lib/CodeGen/OptimizePHIs.cpp
+++ b/lib/CodeGen/OptimizePHIs.cpp
@@ -23,7 +23,7 @@
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
-#define DEBUG_TYPE "phi-opt"
+#define DEBUG_TYPE "opt-phis"
STATISTIC(NumPHICycles, "Number of PHI cycles replaced");
STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles");
@@ -59,7 +59,7 @@ namespace {
char OptimizePHIs::ID = 0;
char &llvm::OptimizePHIsID = OptimizePHIs::ID;
-INITIALIZE_PASS(OptimizePHIs, "opt-phis",
+INITIALIZE_PASS(OptimizePHIs, DEBUG_TYPE,
"Optimize machine instruction PHIs", false, false)
bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) {
diff --git a/lib/CodeGen/PHIElimination.cpp b/lib/CodeGen/PHIElimination.cpp
index db2264b2439d..9c898fa40d7e 100644
--- a/lib/CodeGen/PHIElimination.cpp
+++ b/lib/CodeGen/PHIElimination.cpp
@@ -112,11 +112,11 @@ STATISTIC(NumReused, "Number of reused lowered phis");
char PHIElimination::ID = 0;
char& llvm::PHIEliminationID = PHIElimination::ID;
-INITIALIZE_PASS_BEGIN(PHIElimination, "phi-node-elimination",
+INITIALIZE_PASS_BEGIN(PHIElimination, DEBUG_TYPE,
"Eliminate PHI nodes for register allocation",
false, false)
INITIALIZE_PASS_DEPENDENCY(LiveVariables)
-INITIALIZE_PASS_END(PHIElimination, "phi-node-elimination",
+INITIALIZE_PASS_END(PHIElimination, DEBUG_TYPE,
"Eliminate PHI nodes for register allocation", false, false)
void PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const {
diff --git a/lib/CodeGen/PostRASchedulerList.cpp b/lib/CodeGen/PostRASchedulerList.cpp
index 61dccdde8f1d..f2249f9e37e0 100644
--- a/lib/CodeGen/PostRASchedulerList.cpp
+++ b/lib/CodeGen/PostRASchedulerList.cpp
@@ -200,7 +200,7 @@ namespace {
char &llvm::PostRASchedulerID = PostRAScheduler::ID;
-INITIALIZE_PASS(PostRAScheduler, "post-RA-sched",
+INITIALIZE_PASS(PostRAScheduler, DEBUG_TYPE,
"Post RA top-down list latency scheduler", false, false)
SchedulePostRATDList::SchedulePostRATDList(
@@ -367,7 +367,7 @@ bool PostRAScheduler::runOnMachineFunction(MachineFunction &Fn) {
Scheduler.finishBlock();
// Update register kills
- Scheduler.fixupKills(&MBB);
+ Scheduler.fixupKills(MBB);
}
return true;
diff --git a/lib/CodeGen/ProcessImplicitDefs.cpp b/lib/CodeGen/ProcessImplicitDefs.cpp
index d27ea2f51867..0118580a626a 100644
--- a/lib/CodeGen/ProcessImplicitDefs.cpp
+++ b/lib/CodeGen/ProcessImplicitDefs.cpp
@@ -20,7 +20,7 @@
using namespace llvm;
-#define DEBUG_TYPE "processimplicitdefs"
+#define DEBUG_TYPE "processimpdefs"
namespace {
/// Process IMPLICIT_DEF instructions and make sure there is one implicit_def
@@ -51,9 +51,7 @@ public:
char ProcessImplicitDefs::ID = 0;
char &llvm::ProcessImplicitDefsID = ProcessImplicitDefs::ID;
-INITIALIZE_PASS_BEGIN(ProcessImplicitDefs, "processimpdefs",
- "Process Implicit Definitions", false, false)
-INITIALIZE_PASS_END(ProcessImplicitDefs, "processimpdefs",
+INITIALIZE_PASS(ProcessImplicitDefs, DEBUG_TYPE,
"Process Implicit Definitions", false, false)
void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const {
diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp
index aaa253fde494..a9813e534c5f 100644
--- a/lib/CodeGen/PrologEpilogInserter.cpp
+++ b/lib/CodeGen/PrologEpilogInserter.cpp
@@ -45,7 +45,7 @@
using namespace llvm;
-#define DEBUG_TYPE "pei"
+#define DEBUG_TYPE "prologepilog"
typedef SmallVector<MachineBasicBlock *, 4> MBBVector;
static void doSpillCalleeSavedRegs(MachineFunction &MF, RegScavenger *RS,
@@ -129,12 +129,12 @@ WarnStackSize("warn-stack-size", cl::Hidden, cl::init((unsigned)-1),
cl::desc("Warn for stack size bigger than the given"
" number"));
-INITIALIZE_PASS_BEGIN(PEI, "prologepilog", "Prologue/Epilogue Insertion", false,
+INITIALIZE_PASS_BEGIN(PEI, DEBUG_TYPE, "Prologue/Epilogue Insertion", false,
false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(StackProtector)
-INITIALIZE_PASS_END(PEI, "prologepilog",
+INITIALIZE_PASS_END(PEI, DEBUG_TYPE,
"Prologue/Epilogue Insertion & Frame Finalization", false,
false)
@@ -450,12 +450,13 @@ static void updateLiveness(MachineFunction &MF) {
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
for (MachineBasicBlock *MBB : Visited) {
MCPhysReg Reg = CSI[i].getReg();
// Add the callee-saved register as live-in.
// It's killed at the spill.
- if (!MBB->isLiveIn(Reg))
+ if (!MRI.isReserved(Reg) && !MBB->isLiveIn(Reg))
MBB->addLiveIn(Reg);
}
}
diff --git a/lib/CodeGen/RenameIndependentSubregs.cpp b/lib/CodeGen/RenameIndependentSubregs.cpp
index 2f7ee8bf414c..cc32e43968bb 100644
--- a/lib/CodeGen/RenameIndependentSubregs.cpp
+++ b/lib/CodeGen/RenameIndependentSubregs.cpp
@@ -112,11 +112,11 @@ char RenameIndependentSubregs::ID;
char &llvm::RenameIndependentSubregsID = RenameIndependentSubregs::ID;
-INITIALIZE_PASS_BEGIN(RenameIndependentSubregs, "rename-independent-subregs",
+INITIALIZE_PASS_BEGIN(RenameIndependentSubregs, DEBUG_TYPE,
"Rename Independent Subregisters", false, false)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
-INITIALIZE_PASS_END(RenameIndependentSubregs, "rename-independent-subregs",
+INITIALIZE_PASS_END(RenameIndependentSubregs, DEBUG_TYPE,
"Rename Independent Subregisters", false, false)
bool RenameIndependentSubregs::renameComponents(LiveInterval &LI) const {
diff --git a/lib/CodeGen/SafeStack.cpp b/lib/CodeGen/SafeStack.cpp
index 2771fdbd737a..8584a9b7c897 100644
--- a/lib/CodeGen/SafeStack.cpp
+++ b/lib/CodeGen/SafeStack.cpp
@@ -52,7 +52,7 @@
using namespace llvm;
using namespace llvm::safestack;
-#define DEBUG_TYPE "safestack"
+#define DEBUG_TYPE "safe-stack"
namespace llvm {
@@ -820,10 +820,10 @@ public:
} // anonymous namespace
char SafeStackLegacyPass::ID = 0;
-INITIALIZE_PASS_BEGIN(SafeStackLegacyPass, "safe-stack",
+INITIALIZE_PASS_BEGIN(SafeStackLegacyPass, DEBUG_TYPE,
"Safe Stack instrumentation pass", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
-INITIALIZE_PASS_END(SafeStackLegacyPass, "safe-stack",
+INITIALIZE_PASS_END(SafeStackLegacyPass, DEBUG_TYPE,
"Safe Stack instrumentation pass", false, false)
FunctionPass *llvm::createSafeStackPass() { return new SafeStackLegacyPass(); }
diff --git a/lib/CodeGen/ScalarizeMaskedMemIntrin.cpp b/lib/CodeGen/ScalarizeMaskedMemIntrin.cpp
index dab5b91f50ad..07b43a82ca99 100644
--- a/lib/CodeGen/ScalarizeMaskedMemIntrin.cpp
+++ b/lib/CodeGen/ScalarizeMaskedMemIntrin.cpp
@@ -49,12 +49,8 @@ private:
} // namespace
char ScalarizeMaskedMemIntrin::ID = 0;
-INITIALIZE_PASS_BEGIN(ScalarizeMaskedMemIntrin, "scalarize-masked-mem-intrin",
- "Scalarize unsupported masked memory intrinsics", false,
- false)
-INITIALIZE_PASS_END(ScalarizeMaskedMemIntrin, "scalarize-masked-mem-intrin",
- "Scalarize unsupported masked memory intrinsics", false,
- false)
+INITIALIZE_PASS(ScalarizeMaskedMemIntrin, DEBUG_TYPE,
+ "Scalarize unsupported masked memory intrinsics", false, false)
FunctionPass *llvm::createScalarizeMaskedMemIntrinPass() {
return new ScalarizeMaskedMemIntrin();
diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index 18823b74c47f..8035ea80364b 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -1057,179 +1057,71 @@ void ScheduleDAGInstrs::reduceHugeMemNodeMaps(Value2SUsMap &stores,
loads.dump());
}
-void ScheduleDAGInstrs::startBlockForKills(MachineBasicBlock *BB) {
- // Start with no live registers.
- LiveRegs.reset();
-
- // Examine the live-in regs of all successors.
- for (const MachineBasicBlock *Succ : BB->successors()) {
- for (const auto &LI : Succ->liveins()) {
- // Repeat, for reg and all subregs.
- for (MCSubRegIterator SubRegs(LI.PhysReg, TRI, /*IncludeSelf=*/true);
- SubRegs.isValid(); ++SubRegs)
- LiveRegs.set(*SubRegs);
- }
- }
-}
-
-/// \brief If we change a kill flag on the bundle instruction implicit register
-/// operands, then we also need to propagate that to any instructions inside
-/// the bundle which had the same kill state.
-static void toggleBundleKillFlag(MachineInstr *MI, unsigned Reg,
- bool NewKillState,
- const TargetRegisterInfo *TRI) {
- if (MI->getOpcode() != TargetOpcode::BUNDLE)
- return;
-
- // Walk backwards from the last instruction in the bundle to the first.
- // Once we set a kill flag on an instruction, we bail out, as otherwise we
- // might set it on too many operands. We will clear as many flags as we
- // can though.
- MachineBasicBlock::instr_iterator Begin = MI->getIterator();
- MachineBasicBlock::instr_iterator End = getBundleEnd(Begin);
- while (Begin != End) {
- if (NewKillState) {
- if ((--End)->addRegisterKilled(Reg, TRI, /* addIfNotFound= */ false))
- return;
- } else
- (--End)->clearRegisterKills(Reg, TRI);
- }
-}
-
-void ScheduleDAGInstrs::toggleKillFlag(MachineInstr &MI, MachineOperand &MO) {
- if (MO.isDebug())
- return;
-
- // Setting kill flag...
- if (!MO.isKill()) {
- MO.setIsKill(true);
- toggleBundleKillFlag(&MI, MO.getReg(), true, TRI);
- return;
- }
-
- // If MO itself is live, clear the kill flag...
- if (LiveRegs.test(MO.getReg())) {
- MO.setIsKill(false);
- toggleBundleKillFlag(&MI, MO.getReg(), false, TRI);
- return;
- }
-
- // If any subreg of MO is live, then create an imp-def for that
- // subreg and keep MO marked as killed.
- MO.setIsKill(false);
- toggleBundleKillFlag(&MI, MO.getReg(), false, TRI);
- bool AllDead = true;
- const unsigned SuperReg = MO.getReg();
- MachineInstrBuilder MIB(MF, &MI);
- for (MCSubRegIterator SubRegs(SuperReg, TRI); SubRegs.isValid(); ++SubRegs) {
- if (LiveRegs.test(*SubRegs)) {
- MIB.addReg(*SubRegs, RegState::ImplicitDefine);
- AllDead = false;
- }
- }
+static void toggleKills(const MachineRegisterInfo &MRI, LivePhysRegs &LiveRegs,
+ MachineInstr &MI, bool addToLiveRegs) {
+ for (MachineOperand &MO : MI.operands()) {
+ if (!MO.isReg() || !MO.readsReg())
+ continue;
+ unsigned Reg = MO.getReg();
+ if (!Reg)
+ continue;
- if(AllDead) {
- MO.setIsKill(true);
- toggleBundleKillFlag(&MI, MO.getReg(), true, TRI);
+ // Things that are available after the instruction are killed by it.
+ bool IsKill = LiveRegs.available(MRI, Reg);
+ MO.setIsKill(IsKill);
+ if (IsKill && addToLiveRegs)
+ LiveRegs.addReg(Reg);
}
}
-void ScheduleDAGInstrs::fixupKills(MachineBasicBlock *MBB) {
- // FIXME: Reuse the LivePhysRegs utility for this.
- DEBUG(dbgs() << "Fixup kills for BB#" << MBB->getNumber() << '\n');
-
- LiveRegs.resize(TRI->getNumRegs());
- BitVector killedRegs(TRI->getNumRegs());
+void ScheduleDAGInstrs::fixupKills(MachineBasicBlock &MBB) {
+ DEBUG(dbgs() << "Fixup kills for BB#" << MBB.getNumber() << '\n');
- startBlockForKills(MBB);
+ LiveRegs.init(*TRI);
+ LiveRegs.addLiveOuts(MBB);
// Examine block from end to start...
- unsigned Count = MBB->size();
- for (MachineBasicBlock::iterator I = MBB->end(), E = MBB->begin();
- I != E; --Count) {
- MachineInstr &MI = *--I;
+ for (MachineInstr &MI : make_range(MBB.rbegin(), MBB.rend())) {
if (MI.isDebugValue())
continue;
// Update liveness. Registers that are defed but not used in this
// instruction are now dead. Mark register and all subregs as they
// are completely defined.
- for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI.getOperand(i);
- if (MO.isRegMask())
- LiveRegs.clearBitsNotInMask(MO.getRegMask());
- if (!MO.isReg()) continue;
- unsigned Reg = MO.getReg();
- if (Reg == 0) continue;
- if (!MO.isDef()) continue;
- // Ignore two-addr defs.
- if (MI.isRegTiedToUseOperand(i)) continue;
-
- // Repeat for reg and all subregs.
- for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
- SubRegs.isValid(); ++SubRegs)
- LiveRegs.reset(*SubRegs);
- }
-
- // Examine all used registers and set/clear kill flag. When a
- // register is used multiple times we only set the kill flag on
- // the first use. Don't set kill flags on undef operands.
- killedRegs.reset();
-
- // toggleKillFlag can append new operands (implicit defs), so using
- // a range-based loop is not safe. The new operands will be appended
- // at the end of the operand list and they don't need to be visited,
- // so iterating until the currently last operand is ok.
- for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI.getOperand(i);
- if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue;
- unsigned Reg = MO.getReg();
- if ((Reg == 0) || MRI.isReserved(Reg)) continue;
-
- bool kill = false;
- if (!killedRegs.test(Reg)) {
- kill = true;
- // A register is not killed if any subregs are live...
- for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) {
- if (LiveRegs.test(*SubRegs)) {
- kill = false;
- break;
- }
- }
-
- // If subreg is not live, then register is killed if it became
- // live in this instruction
- if (kill)
- kill = !LiveRegs.test(Reg);
- }
-
- if (MO.isKill() != kill) {
- DEBUG(dbgs() << "Fixing " << MO << " in ");
- toggleKillFlag(MI, MO);
- DEBUG(MI.dump());
- DEBUG({
- if (MI.getOpcode() == TargetOpcode::BUNDLE) {
- MachineBasicBlock::instr_iterator Begin = MI.getIterator();
- MachineBasicBlock::instr_iterator End = getBundleEnd(Begin);
- while (++Begin != End)
- DEBUG(Begin->dump());
- }
- });
+ for (ConstMIBundleOperands O(MI); O.isValid(); ++O) {
+ const MachineOperand &MO = *O;
+ if (MO.isReg()) {
+ if (!MO.isDef())
+ continue;
+ unsigned Reg = MO.getReg();
+ if (!Reg)
+ continue;
+ LiveRegs.removeReg(Reg);
+ } else if (MO.isRegMask()) {
+ LiveRegs.removeRegsInMask(MO);
}
-
- killedRegs.set(Reg);
}
- // Mark any used register (that is not using undef) and subregs as
- // now live...
- for (const MachineOperand &MO : MI.operands()) {
- if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue;
- unsigned Reg = MO.getReg();
- if ((Reg == 0) || MRI.isReserved(Reg)) continue;
-
- for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/true);
- SubRegs.isValid(); ++SubRegs)
- LiveRegs.set(*SubRegs);
+ // If there is a bundle header fix it up first.
+ if (!MI.isBundled()) {
+ toggleKills(MRI, LiveRegs, MI, true);
+ } else {
+ MachineBasicBlock::instr_iterator First = MI.getIterator();
+ if (MI.isBundle()) {
+ toggleKills(MRI, LiveRegs, MI, false);
+ ++First;
+ }
+ // Some targets make the (questionable) assumtion that the instructions
+ // inside the bundle are ordered and consequently only the last use of
+ // a register inside the bundle can kill it.
+ MachineBasicBlock::instr_iterator I = std::next(First);
+ while (I->isBundledWithSucc())
+ ++I;
+ do {
+ if (!I->isDebugValue())
+ toggleKills(MRI, LiveRegs, *I, true);
+ --I;
+ } while(I != First);
}
}
}
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 5d450e7e078c..23a302f3e561 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -12349,9 +12349,9 @@ bool DAGCombiner::MergeStoresOfConstantsOrVecElts(
SDValue Val = St->getValue();
StoreInt <<= ElementSizeBytes * 8;
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val)) {
- StoreInt |= C->getAPIntValue().zext(SizeInBits);
+ StoreInt |= C->getAPIntValue().zextOrTrunc(SizeInBits);
} else if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Val)) {
- StoreInt |= C->getValueAPF().bitcastToAPInt().zext(SizeInBits);
+ StoreInt |= C->getValueAPF().bitcastToAPInt().zextOrTrunc(SizeInBits);
} else {
llvm_unreachable("Invalid constant element type");
}
@@ -12617,16 +12617,19 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
EVT StoreTy = EVT::getIntegerVT(Context, SizeInBits);
bool IsFast = false;
if (TLI.isTypeLegal(StoreTy) &&
+ TLI.canMergeStoresTo(FirstStoreAS, StoreTy) &&
TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstStoreAS,
FirstStoreAlign, &IsFast) &&
IsFast) {
LastLegalType = i + 1;
// Or check whether a truncstore is legal.
- } else if (TLI.getTypeAction(Context, StoreTy) ==
+ } else if (!LegalTypes &&
+ TLI.getTypeAction(Context, StoreTy) ==
TargetLowering::TypePromoteInteger) {
EVT LegalizedStoredValueTy =
TLI.getTypeToTransformTo(Context, StoredVal.getValueType());
if (TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) &&
+ TLI.canMergeStoresTo(FirstStoreAS, LegalizedStoredValueTy) &&
TLI.allowsMemoryAccess(Context, DL, LegalizedStoredValueTy,
FirstStoreAS, FirstStoreAlign, &IsFast) &&
IsFast) {
@@ -12642,7 +12645,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
!NoVectors) {
// Find a legal type for the vector store.
EVT Ty = EVT::getVectorVT(Context, MemVT, i + 1);
- if (TLI.isTypeLegal(Ty) && TLI.canMergeStoresTo(Ty) &&
+ if (TLI.isTypeLegal(Ty) && TLI.canMergeStoresTo(FirstStoreAS, Ty) &&
TLI.allowsMemoryAccess(Context, DL, Ty, FirstStoreAS,
FirstStoreAlign, &IsFast) &&
IsFast)
@@ -12700,7 +12703,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
EVT Ty =
EVT::getVectorVT(*DAG.getContext(), MemVT.getScalarType(), Elts);
bool IsFast;
- if (TLI.isTypeLegal(Ty) &&
+ if (TLI.isTypeLegal(Ty) && TLI.canMergeStoresTo(FirstStoreAS, Ty) &&
TLI.allowsMemoryAccess(Context, DL, Ty, FirstStoreAS,
FirstStoreAlign, &IsFast) &&
IsFast)
@@ -12810,6 +12813,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
EVT StoreTy = EVT::getVectorVT(Context, MemVT, i + 1);
bool IsFastSt, IsFastLd;
if (TLI.isTypeLegal(StoreTy) &&
+ TLI.canMergeStoresTo(FirstStoreAS, StoreTy) &&
TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstStoreAS,
FirstStoreAlign, &IsFastSt) &&
IsFastSt &&
@@ -12823,6 +12827,7 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
unsigned SizeInBits = (i + 1) * ElementSizeBytes * 8;
StoreTy = EVT::getIntegerVT(Context, SizeInBits);
if (TLI.isTypeLegal(StoreTy) &&
+ TLI.canMergeStoresTo(FirstStoreAS, StoreTy) &&
TLI.allowsMemoryAccess(Context, DL, StoreTy, FirstStoreAS,
FirstStoreAlign, &IsFastSt) &&
IsFastSt &&
@@ -12834,7 +12839,9 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
else if (TLI.getTypeAction(Context, StoreTy) ==
TargetLowering::TypePromoteInteger) {
EVT LegalizedStoredValueTy = TLI.getTypeToTransformTo(Context, StoreTy);
- if (TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) &&
+ if (!LegalTypes &&
+ TLI.isTruncStoreLegal(LegalizedStoredValueTy, StoreTy) &&
+ TLI.canMergeStoresTo(FirstStoreAS, LegalizedStoredValueTy) &&
TLI.isLoadExtLegal(ISD::ZEXTLOAD, LegalizedStoredValueTy,
StoreTy) &&
TLI.isLoadExtLegal(ISD::SEXTLOAD, LegalizedStoredValueTy,
@@ -14455,6 +14462,145 @@ SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *N) {
return SDValue();
}
+/// If we are extracting a subvector produced by a wide binary operator with at
+/// at least one operand that was the result of a vector concatenation, then try
+/// to use the narrow vector operands directly to avoid the concatenation and
+/// extraction.
+static SDValue narrowExtractedVectorBinOp(SDNode *Extract, SelectionDAG &DAG) {
+ // TODO: Refactor with the caller (visitEXTRACT_SUBVECTOR), so we can share
+ // some of these bailouts with other transforms.
+
+ // The extract index must be a constant, so we can map it to a concat operand.
+ auto *ExtractIndex = dyn_cast<ConstantSDNode>(Extract->getOperand(1));
+ if (!ExtractIndex)
+ return SDValue();
+
+ // Only handle the case where we are doubling and then halving. A larger ratio
+ // may require more than two narrow binops to replace the wide binop.
+ EVT VT = Extract->getValueType(0);
+ unsigned NumElems = VT.getVectorNumElements();
+ assert((ExtractIndex->getZExtValue() % NumElems) == 0 &&
+ "Extract index is not a multiple of the vector length.");
+ if (Extract->getOperand(0).getValueSizeInBits() != VT.getSizeInBits() * 2)
+ return SDValue();
+
+ // We are looking for an optionally bitcasted wide vector binary operator
+ // feeding an extract subvector.
+ SDValue BinOp = Extract->getOperand(0);
+ if (BinOp.getOpcode() == ISD::BITCAST)
+ BinOp = BinOp.getOperand(0);
+
+ // TODO: The motivating case for this transform is an x86 AVX1 target. That
+ // target has temptingly almost legal versions of bitwise logic ops in 256-bit
+ // flavors, but no other 256-bit integer support. This could be extended to
+ // handle any binop, but that may require fixing/adding other folds to avoid
+ // codegen regressions.
+ unsigned BOpcode = BinOp.getOpcode();
+ if (BOpcode != ISD::AND && BOpcode != ISD::OR && BOpcode != ISD::XOR)
+ return SDValue();
+
+ // The binop must be a vector type, so we can chop it in half.
+ EVT WideBVT = BinOp.getValueType();
+ if (!WideBVT.isVector())
+ return SDValue();
+
+ // Bail out if the target does not support a narrower version of the binop.
+ EVT NarrowBVT = EVT::getVectorVT(*DAG.getContext(), WideBVT.getScalarType(),
+ WideBVT.getVectorNumElements() / 2);
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ if (!TLI.isOperationLegalOrCustomOrPromote(BOpcode, NarrowBVT))
+ return SDValue();
+
+ // Peek through bitcasts of the binary operator operands if needed.
+ SDValue LHS = BinOp.getOperand(0);
+ if (LHS.getOpcode() == ISD::BITCAST)
+ LHS = LHS.getOperand(0);
+
+ SDValue RHS = BinOp.getOperand(1);
+ if (RHS.getOpcode() == ISD::BITCAST)
+ RHS = RHS.getOperand(0);
+
+ // We need at least one concatenation operation of a binop operand to make
+ // this transform worthwhile. The concat must double the input vector sizes.
+ // TODO: Should we also handle INSERT_SUBVECTOR patterns?
+ bool ConcatL =
+ LHS.getOpcode() == ISD::CONCAT_VECTORS && LHS.getNumOperands() == 2;
+ bool ConcatR =
+ RHS.getOpcode() == ISD::CONCAT_VECTORS && RHS.getNumOperands() == 2;
+ if (!ConcatL && !ConcatR)
+ return SDValue();
+
+ // If one of the binop operands was not the result of a concat, we must
+ // extract a half-sized operand for our new narrow binop. We can't just reuse
+ // the original extract index operand because we may have bitcasted.
+ unsigned ConcatOpNum = ExtractIndex->getZExtValue() / NumElems;
+ unsigned ExtBOIdx = ConcatOpNum * NarrowBVT.getVectorNumElements();
+ EVT ExtBOIdxVT = Extract->getOperand(1).getValueType();
+ SDLoc DL(Extract);
+
+ // extract (binop (concat X1, X2), (concat Y1, Y2)), N --> binop XN, YN
+ // extract (binop (concat X1, X2), Y), N --> binop XN, (extract Y, N)
+ // extract (binop X, (concat Y1, Y2)), N --> binop (extract X, N), YN
+ SDValue X = ConcatL ? DAG.getBitcast(NarrowBVT, LHS.getOperand(ConcatOpNum))
+ : DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, NarrowBVT,
+ BinOp.getOperand(0),
+ DAG.getConstant(ExtBOIdx, DL, ExtBOIdxVT));
+
+ SDValue Y = ConcatR ? DAG.getBitcast(NarrowBVT, RHS.getOperand(ConcatOpNum))
+ : DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, NarrowBVT,
+ BinOp.getOperand(1),
+ DAG.getConstant(ExtBOIdx, DL, ExtBOIdxVT));
+
+ SDValue NarrowBinOp = DAG.getNode(BOpcode, DL, NarrowBVT, X, Y);
+ return DAG.getBitcast(VT, NarrowBinOp);
+}
+
+/// If we are extracting a subvector from a wide vector load, convert to a
+/// narrow load to eliminate the extraction:
+/// (extract_subvector (load wide vector)) --> (load narrow vector)
+static SDValue narrowExtractedVectorLoad(SDNode *Extract, SelectionDAG &DAG) {
+ // TODO: Add support for big-endian. The offset calculation must be adjusted.
+ if (DAG.getDataLayout().isBigEndian())
+ return SDValue();
+
+ // TODO: The one-use check is overly conservative. Check the cost of the
+ // extract instead or remove that condition entirely.
+ auto *Ld = dyn_cast<LoadSDNode>(Extract->getOperand(0));
+ auto *ExtIdx = dyn_cast<ConstantSDNode>(Extract->getOperand(1));
+ if (!Ld || !Ld->hasOneUse() || Ld->isVolatile() || !ExtIdx)
+ return SDValue();
+
+ // The narrow load will be offset from the base address of the old load if
+ // we are extracting from something besides index 0 (little-endian).
+ EVT VT = Extract->getValueType(0);
+ SDLoc DL(Extract);
+ SDValue BaseAddr = Ld->getOperand(1);
+ unsigned Offset = ExtIdx->getZExtValue() * VT.getScalarType().getStoreSize();
+
+ // TODO: Use "BaseIndexOffset" to make this more effective.
+ SDValue NewAddr = DAG.getMemBasePlusOffset(BaseAddr, Offset, DL);
+ MachineFunction &MF = DAG.getMachineFunction();
+ 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);
+ }
+
+ return NewLd;
+}
+
SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode* N) {
EVT NVT = N->getValueType(0);
SDValue V = N->getOperand(0);
@@ -14463,6 +14609,10 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode* N) {
if (V.isUndef())
return DAG.getUNDEF(NVT);
+ if (TLI.isOperationLegalOrCustomOrPromote(ISD::LOAD, NVT))
+ if (SDValue NarrowLoad = narrowExtractedVectorLoad(N, DAG))
+ return NarrowLoad;
+
// Combine:
// (extract_subvec (concat V1, V2, ...), i)
// Into:
@@ -14510,6 +14660,9 @@ SDValue DAGCombiner::visitEXTRACT_SUBVECTOR(SDNode* N) {
}
}
+ if (SDValue NarrowBOp = narrowExtractedVectorBinOp(N, DAG))
+ return NarrowBOp;
+
return SDValue();
}
@@ -14745,10 +14898,10 @@ static SDValue combineShuffleOfScalars(ShuffleVectorSDNode *SVN,
// This is often generated during legalization.
// e.g. v4i32 <0,u,1,u> -> (v2i64 any_vector_extend_in_reg(v4i32 src))
// TODO Add support for ZERO_EXTEND_VECTOR_INREG when we have a test case.
-SDValue combineShuffleToVectorExtend(ShuffleVectorSDNode *SVN,
- SelectionDAG &DAG,
- const TargetLowering &TLI,
- bool LegalOperations) {
+static SDValue combineShuffleToVectorExtend(ShuffleVectorSDNode *SVN,
+ SelectionDAG &DAG,
+ const TargetLowering &TLI,
+ bool LegalOperations) {
EVT VT = SVN->getValueType(0);
bool IsBigEndian = DAG.getDataLayout().isBigEndian();
@@ -14795,7 +14948,8 @@ SDValue combineShuffleToVectorExtend(ShuffleVectorSDNode *SVN,
// destination type. This is often generated during legalization.
// If the source node itself was a '*_extend_vector_inreg' node then we should
// then be able to remove it.
-SDValue combineTruncationShuffle(ShuffleVectorSDNode *SVN, SelectionDAG &DAG) {
+static SDValue combineTruncationShuffle(ShuffleVectorSDNode *SVN,
+ SelectionDAG &DAG) {
EVT VT = SVN->getValueType(0);
bool IsBigEndian = DAG.getDataLayout().isBigEndian();
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 9a47a914df91..d0a8b34c69c6 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -899,6 +899,39 @@ void SelectionDAGLegalize::LegalizeLoadOps(SDNode *Node) {
}
}
+static TargetLowering::LegalizeAction
+getStrictFPOpcodeAction(const TargetLowering &TLI, unsigned Opcode, EVT VT) {
+ unsigned EqOpc;
+ switch (Opcode) {
+ default: llvm_unreachable("Unexpected FP pseudo-opcode");
+ case ISD::STRICT_FSQRT: EqOpc = ISD::FSQRT; break;
+ case ISD::STRICT_FPOW: EqOpc = ISD::FPOW; break;
+ case ISD::STRICT_FPOWI: EqOpc = ISD::FPOWI; break;
+ case ISD::STRICT_FSIN: EqOpc = ISD::FSIN; break;
+ case ISD::STRICT_FCOS: EqOpc = ISD::FCOS; break;
+ case ISD::STRICT_FEXP: EqOpc = ISD::FEXP; break;
+ case ISD::STRICT_FEXP2: EqOpc = ISD::FEXP2; break;
+ case ISD::STRICT_FLOG: EqOpc = ISD::FLOG; break;
+ case ISD::STRICT_FLOG10: EqOpc = ISD::FLOG10; break;
+ case ISD::STRICT_FLOG2: EqOpc = ISD::FLOG2; break;
+ case ISD::STRICT_FRINT: EqOpc = ISD::FRINT; break;
+ case ISD::STRICT_FNEARBYINT: EqOpc = ISD::FNEARBYINT; break;
+ }
+
+ auto Action = TLI.getOperationAction(EqOpc, VT);
+
+ // We don't currently handle Custom or Promote for strict FP pseudo-ops.
+ // For now, we just expand for those cases.
+ if (Action != TargetLowering::Legal)
+ Action = TargetLowering::Expand;
+
+ // ISD::FPOWI returns 'Legal' even though it should be expanded.
+ if (Opcode == ISD::STRICT_FPOWI && Action == TargetLowering::Legal)
+ Action = TargetLowering::Expand;
+
+ return Action;
+}
+
/// Return a legal replacement for the given operation, with all legal operands.
void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
DEBUG(dbgs() << "\nLegalizing: "; Node->dump(&DAG));
@@ -1043,6 +1076,25 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
return;
}
break;
+ case ISD::STRICT_FSQRT:
+ case ISD::STRICT_FPOW:
+ case ISD::STRICT_FPOWI:
+ case ISD::STRICT_FSIN:
+ case ISD::STRICT_FCOS:
+ case ISD::STRICT_FEXP:
+ case ISD::STRICT_FEXP2:
+ case ISD::STRICT_FLOG:
+ case ISD::STRICT_FLOG10:
+ case ISD::STRICT_FLOG2:
+ case ISD::STRICT_FRINT:
+ case ISD::STRICT_FNEARBYINT:
+ // These pseudo-ops get legalized as if they were their non-strict
+ // equivalent. For instance, if ISD::FSQRT is legal then ISD::STRICT_FSQRT
+ // is also legal, but if ISD::FSQRT requires expansion then so does
+ // ISD::STRICT_FSQRT.
+ Action = getStrictFPOpcodeAction(TLI, Node->getOpcode(),
+ Node->getValueType(0));
+ break;
default:
if (Node->getOpcode() >= ISD::BUILTIN_OP_END) {
@@ -2032,6 +2084,9 @@ SDValue SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node,
RTLIB::Libcall Call_F80,
RTLIB::Libcall Call_F128,
RTLIB::Libcall Call_PPCF128) {
+ if (Node->isStrictFPOpcode())
+ Node = DAG.mutateStrictFPToFP(Node);
+
RTLIB::Libcall LC;
switch (Node->getSimpleValueType(0).SimpleTy) {
default: llvm_unreachable("Unexpected request for libcall!");
@@ -3907,16 +3962,19 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
RTLIB::FMAX_PPCF128));
break;
case ISD::FSQRT:
+ case ISD::STRICT_FSQRT:
Results.push_back(ExpandFPLibCall(Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
RTLIB::SQRT_F80, RTLIB::SQRT_F128,
RTLIB::SQRT_PPCF128));
break;
case ISD::FSIN:
+ case ISD::STRICT_FSIN:
Results.push_back(ExpandFPLibCall(Node, RTLIB::SIN_F32, RTLIB::SIN_F64,
RTLIB::SIN_F80, RTLIB::SIN_F128,
RTLIB::SIN_PPCF128));
break;
case ISD::FCOS:
+ case ISD::STRICT_FCOS:
Results.push_back(ExpandFPLibCall(Node, RTLIB::COS_F32, RTLIB::COS_F64,
RTLIB::COS_F80, RTLIB::COS_F128,
RTLIB::COS_PPCF128));
@@ -3926,26 +3984,31 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
ExpandSinCosLibCall(Node, Results);
break;
case ISD::FLOG:
+ case ISD::STRICT_FLOG:
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
RTLIB::LOG_F80, RTLIB::LOG_F128,
RTLIB::LOG_PPCF128));
break;
case ISD::FLOG2:
+ case ISD::STRICT_FLOG2:
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
RTLIB::LOG2_F80, RTLIB::LOG2_F128,
RTLIB::LOG2_PPCF128));
break;
case ISD::FLOG10:
+ case ISD::STRICT_FLOG10:
Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
RTLIB::LOG10_F80, RTLIB::LOG10_F128,
RTLIB::LOG10_PPCF128));
break;
case ISD::FEXP:
+ case ISD::STRICT_FEXP:
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64,
RTLIB::EXP_F80, RTLIB::EXP_F128,
RTLIB::EXP_PPCF128));
break;
case ISD::FEXP2:
+ case ISD::STRICT_FEXP2:
Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
RTLIB::EXP2_F80, RTLIB::EXP2_F128,
RTLIB::EXP2_PPCF128));
@@ -3966,11 +4029,13 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
RTLIB::CEIL_PPCF128));
break;
case ISD::FRINT:
+ case ISD::STRICT_FRINT:
Results.push_back(ExpandFPLibCall(Node, RTLIB::RINT_F32, RTLIB::RINT_F64,
RTLIB::RINT_F80, RTLIB::RINT_F128,
RTLIB::RINT_PPCF128));
break;
case ISD::FNEARBYINT:
+ case ISD::STRICT_FNEARBYINT:
Results.push_back(ExpandFPLibCall(Node, RTLIB::NEARBYINT_F32,
RTLIB::NEARBYINT_F64,
RTLIB::NEARBYINT_F80,
@@ -3985,11 +4050,13 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
RTLIB::ROUND_PPCF128));
break;
case ISD::FPOWI:
+ case ISD::STRICT_FPOWI:
Results.push_back(ExpandFPLibCall(Node, RTLIB::POWI_F32, RTLIB::POWI_F64,
RTLIB::POWI_F80, RTLIB::POWI_F128,
RTLIB::POWI_PPCF128));
break;
case ISD::FPOW:
+ case ISD::STRICT_FPOW:
Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64,
RTLIB::POW_F80, RTLIB::POW_F128,
RTLIB::POW_PPCF128));
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 16c1f78f1b35..177898e1e950 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4779,23 +4779,23 @@ static bool FindOptimalMemOpLowering(std::vector<EVT> &MemOps,
DAG.getMachineFunction());
if (VT == MVT::Other) {
- if (DstAlign >= DAG.getDataLayout().getPointerPrefAlignment(DstAS) ||
- TLI.allowsMisalignedMemoryAccesses(VT, DstAS, DstAlign)) {
- VT = TLI.getPointerTy(DAG.getDataLayout(), DstAS);
- } else {
- switch (DstAlign & 7) {
- case 0: VT = MVT::i64; break;
- case 4: VT = MVT::i32; break;
- case 2: VT = MVT::i16; break;
- default: VT = MVT::i8; break;
- }
- }
-
+ // Use the largest integer type whose alignment constraints are satisfied.
+ // We only need to check DstAlign here as SrcAlign is always greater or
+ // equal to DstAlign (or zero).
+ VT = MVT::i64;
+ while (DstAlign && DstAlign < VT.getSizeInBits() / 8 &&
+ !TLI.allowsMisalignedMemoryAccesses(VT, DstAS, DstAlign))
+ VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1);
+ assert(VT.isInteger());
+
+ // Find the largest legal integer type.
MVT LVT = MVT::i64;
while (!TLI.isTypeLegal(LVT))
LVT = (MVT::SimpleValueType)(LVT.SimpleTy - 1);
assert(LVT.isInteger());
+ // If the type we've chosen is larger than the largest legal integer type
+ // then use that instead.
if (VT.bitsGT(LVT))
VT = LVT;
}
@@ -6542,6 +6542,63 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
return N;
}
+SDNode* SelectionDAG::mutateStrictFPToFP(SDNode *Node) {
+ unsigned OrigOpc = Node->getOpcode();
+ unsigned NewOpc;
+ bool IsUnary = false;
+ switch (OrigOpc) {
+ default:
+ llvm_unreachable("mutateStrictFPToFP called with unexpected opcode!");
+ case ISD::STRICT_FADD: NewOpc = ISD::FADD; break;
+ case ISD::STRICT_FSUB: NewOpc = ISD::FSUB; break;
+ case ISD::STRICT_FMUL: NewOpc = ISD::FMUL; break;
+ case ISD::STRICT_FDIV: NewOpc = ISD::FDIV; break;
+ case ISD::STRICT_FREM: NewOpc = ISD::FREM; break;
+ case ISD::STRICT_FSQRT: NewOpc = ISD::FSQRT; IsUnary = true; break;
+ case ISD::STRICT_FPOW: NewOpc = ISD::FPOW; break;
+ case ISD::STRICT_FPOWI: NewOpc = ISD::FPOWI; break;
+ case ISD::STRICT_FSIN: NewOpc = ISD::FSIN; IsUnary = true; break;
+ case ISD::STRICT_FCOS: NewOpc = ISD::FCOS; IsUnary = true; break;
+ case ISD::STRICT_FEXP: NewOpc = ISD::FEXP; IsUnary = true; break;
+ case ISD::STRICT_FEXP2: NewOpc = ISD::FEXP2; IsUnary = true; break;
+ case ISD::STRICT_FLOG: NewOpc = ISD::FLOG; IsUnary = true; break;
+ case ISD::STRICT_FLOG10: NewOpc = ISD::FLOG10; IsUnary = true; break;
+ case ISD::STRICT_FLOG2: NewOpc = ISD::FLOG2; IsUnary = true; break;
+ case ISD::STRICT_FRINT: NewOpc = ISD::FRINT; IsUnary = true; break;
+ case ISD::STRICT_FNEARBYINT:
+ NewOpc = ISD::FNEARBYINT;
+ IsUnary = true;
+ break;
+ }
+
+ // We're taking this node out of the chain, so we need to re-link things.
+ SDValue InputChain = Node->getOperand(0);
+ SDValue OutputChain = SDValue(Node, 1);
+ ReplaceAllUsesOfValueWith(OutputChain, InputChain);
+
+ SDVTList VTs = getVTList(Node->getOperand(1).getValueType());
+ SDNode *Res = nullptr;
+ if (IsUnary)
+ Res = MorphNodeTo(Node, NewOpc, VTs, { Node->getOperand(1) });
+ else
+ Res = MorphNodeTo(Node, NewOpc, VTs, { Node->getOperand(1),
+ Node->getOperand(2) });
+
+ // MorphNodeTo can operate in two ways: if an existing node with the
+ // specified operands exists, it can just return it. Otherwise, it
+ // updates the node in place to have the requested operands.
+ if (Res == Node) {
+ // If we updated the node in place, reset the node ID. To the isel,
+ // this should be just like a newly allocated machine node.
+ Res->setNodeId(-1);
+ } else {
+ ReplaceAllUsesWith(Node, Res);
+ RemoveDeadNode(Node);
+ }
+
+ return Res;
+}
+
/// getMachineNode - These are used for target selectors to create a new node
/// with specified return type(s), MachineInstr opcode, and operands.
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 57d340c41c39..b895da21a7ff 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4736,24 +4736,15 @@ SDDbgValue *SelectionDAGBuilder::getDbgValue(SDValue N,
DIExpression *Expr, int64_t Offset,
const DebugLoc &dl,
unsigned DbgSDNodeOrder) {
- SDDbgValue *SDV;
- auto *FISDN = dyn_cast<FrameIndexSDNode>(N.getNode());
- if (FISDN && Expr->startsWithDeref()) {
+ if (auto *FISDN = dyn_cast<FrameIndexSDNode>(N.getNode())) {
// Construct a FrameIndexDbgValue for FrameIndexSDNodes so we can describe
// stack slot locations as such instead of as indirectly addressed
// locations.
- ArrayRef<uint64_t> TrailingElements(Expr->elements_begin() + 1,
- Expr->elements_end());
- DIExpression *DerefedDIExpr =
- DIExpression::get(*DAG.getContext(), TrailingElements);
- int FI = FISDN->getIndex();
- SDV = DAG.getFrameIndexDbgValue(Variable, DerefedDIExpr, FI, 0, dl,
- DbgSDNodeOrder);
- } else {
- SDV = DAG.getDbgValue(Variable, Expr, N.getNode(), N.getResNo(), false,
- Offset, dl, DbgSDNodeOrder);
+ return DAG.getFrameIndexDbgValue(Variable, Expr, FISDN->getIndex(), 0, dl,
+ DbgSDNodeOrder);
}
- return SDV;
+ return DAG.getDbgValue(Variable, Expr, N.getNode(), N.getResNo(), false,
+ Offset, dl, DbgSDNodeOrder);
}
// VisualStudio defines setjmp as _setjmp
@@ -5254,7 +5245,19 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
case Intrinsic::experimental_constrained_fmul:
case Intrinsic::experimental_constrained_fdiv:
case Intrinsic::experimental_constrained_frem:
- visitConstrainedFPIntrinsic(I, Intrinsic);
+ case Intrinsic::experimental_constrained_sqrt:
+ case Intrinsic::experimental_constrained_pow:
+ case Intrinsic::experimental_constrained_powi:
+ case Intrinsic::experimental_constrained_sin:
+ case Intrinsic::experimental_constrained_cos:
+ case Intrinsic::experimental_constrained_exp:
+ case Intrinsic::experimental_constrained_exp2:
+ case Intrinsic::experimental_constrained_log:
+ case Intrinsic::experimental_constrained_log10:
+ case Intrinsic::experimental_constrained_log2:
+ case Intrinsic::experimental_constrained_rint:
+ case Intrinsic::experimental_constrained_nearbyint:
+ visitConstrainedFPIntrinsic(cast<ConstrainedFPIntrinsic>(I));
return nullptr;
case Intrinsic::fmuladd: {
EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType());
@@ -5752,11 +5755,11 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
}
}
-void SelectionDAGBuilder::visitConstrainedFPIntrinsic(const CallInst &I,
- unsigned Intrinsic) {
+void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
+ const ConstrainedFPIntrinsic &FPI) {
SDLoc sdl = getCurSDLoc();
unsigned Opcode;
- switch (Intrinsic) {
+ switch (FPI.getIntrinsicID()) {
default: llvm_unreachable("Impossible intrinsic"); // Can't reach here.
case Intrinsic::experimental_constrained_fadd:
Opcode = ISD::STRICT_FADD;
@@ -5773,23 +5776,64 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(const CallInst &I,
case Intrinsic::experimental_constrained_frem:
Opcode = ISD::STRICT_FREM;
break;
+ case Intrinsic::experimental_constrained_sqrt:
+ Opcode = ISD::STRICT_FSQRT;
+ break;
+ case Intrinsic::experimental_constrained_pow:
+ Opcode = ISD::STRICT_FPOW;
+ break;
+ case Intrinsic::experimental_constrained_powi:
+ Opcode = ISD::STRICT_FPOWI;
+ break;
+ case Intrinsic::experimental_constrained_sin:
+ Opcode = ISD::STRICT_FSIN;
+ break;
+ case Intrinsic::experimental_constrained_cos:
+ Opcode = ISD::STRICT_FCOS;
+ break;
+ case Intrinsic::experimental_constrained_exp:
+ Opcode = ISD::STRICT_FEXP;
+ break;
+ case Intrinsic::experimental_constrained_exp2:
+ Opcode = ISD::STRICT_FEXP2;
+ break;
+ case Intrinsic::experimental_constrained_log:
+ Opcode = ISD::STRICT_FLOG;
+ break;
+ case Intrinsic::experimental_constrained_log10:
+ Opcode = ISD::STRICT_FLOG10;
+ break;
+ case Intrinsic::experimental_constrained_log2:
+ Opcode = ISD::STRICT_FLOG2;
+ break;
+ case Intrinsic::experimental_constrained_rint:
+ Opcode = ISD::STRICT_FRINT;
+ break;
+ case Intrinsic::experimental_constrained_nearbyint:
+ Opcode = ISD::STRICT_FNEARBYINT;
+ break;
}
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDValue Chain = getRoot();
- SDValue Ops[3] = { Chain, getValue(I.getArgOperand(0)),
- getValue(I.getArgOperand(1)) };
SmallVector<EVT, 4> ValueVTs;
- ComputeValueVTs(TLI, DAG.getDataLayout(), I.getType(), ValueVTs);
+ ComputeValueVTs(TLI, DAG.getDataLayout(), FPI.getType(), ValueVTs);
ValueVTs.push_back(MVT::Other); // Out chain
SDVTList VTs = DAG.getVTList(ValueVTs);
- SDValue Result = DAG.getNode(Opcode, sdl, VTs, Ops);
+ SDValue Result;
+ if (FPI.isUnaryOp())
+ Result = DAG.getNode(Opcode, sdl, VTs,
+ { Chain, getValue(FPI.getArgOperand(0)) });
+ else
+ Result = DAG.getNode(Opcode, sdl, VTs,
+ { Chain, getValue(FPI.getArgOperand(0)),
+ getValue(FPI.getArgOperand(1)) });
assert(Result.getNode()->getNumValues() == 2);
SDValue OutChain = Result.getValue(1);
DAG.setRoot(OutChain);
SDValue FPResult = Result.getValue(0);
- setValue(&I, FPResult);
+ setValue(&FPI, FPResult);
}
std::pair<SDValue, SDValue>
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
index bdaee858da61..77e131fa551c 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
@@ -895,7 +895,7 @@ private:
void visitInlineAsm(ImmutableCallSite CS);
const char *visitIntrinsicCall(const CallInst &I, unsigned Intrinsic);
void visitTargetIntrinsic(const CallInst &I, unsigned Intrinsic);
- void visitConstrainedFPIntrinsic(const CallInst &I, unsigned Intrinsic);
+ void visitConstrainedFPIntrinsic(const ConstrainedFPIntrinsic &FPI);
void visitVAStart(const CallInst &I);
void visitVAArg(const VAArgInst &I);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 5e0feccb6b4c..687b882c5e4d 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -905,50 +905,6 @@ public:
} // end anonymous namespace
-static bool isStrictFPOp(SDNode *Node, unsigned &NewOpc) {
- unsigned OrigOpc = Node->getOpcode();
- switch (OrigOpc) {
- case ISD::STRICT_FADD: NewOpc = ISD::FADD; return true;
- case ISD::STRICT_FSUB: NewOpc = ISD::FSUB; return true;
- case ISD::STRICT_FMUL: NewOpc = ISD::FMUL; return true;
- case ISD::STRICT_FDIV: NewOpc = ISD::FDIV; return true;
- case ISD::STRICT_FREM: NewOpc = ISD::FREM; return true;
- default: return false;
- }
-}
-
-SDNode* SelectionDAGISel::MutateStrictFPToFP(SDNode *Node, unsigned NewOpc) {
- assert(((Node->getOpcode() == ISD::STRICT_FADD && NewOpc == ISD::FADD) ||
- (Node->getOpcode() == ISD::STRICT_FSUB && NewOpc == ISD::FSUB) ||
- (Node->getOpcode() == ISD::STRICT_FMUL && NewOpc == ISD::FMUL) ||
- (Node->getOpcode() == ISD::STRICT_FDIV && NewOpc == ISD::FDIV) ||
- (Node->getOpcode() == ISD::STRICT_FREM && NewOpc == ISD::FREM)) &&
- "Unexpected StrictFP opcode!");
-
- // We're taking this node out of the chain, so we need to re-link things.
- SDValue InputChain = Node->getOperand(0);
- SDValue OutputChain = SDValue(Node, 1);
- CurDAG->ReplaceAllUsesOfValueWith(OutputChain, InputChain);
-
- SDVTList VTs = CurDAG->getVTList(Node->getOperand(1).getValueType());
- SDValue Ops[2] = { Node->getOperand(1), Node->getOperand(2) };
- SDNode *Res = CurDAG->MorphNodeTo(Node, NewOpc, VTs, Ops);
-
- // MorphNodeTo can operate in two ways: if an existing node with the
- // specified operands exists, it can just return it. Otherwise, it
- // updates the node in place to have the requested operands.
- if (Res == Node) {
- // If we updated the node in place, reset the node ID. To the isel,
- // this should be just like a newly allocated machine node.
- Res->setNodeId(-1);
- } else {
- CurDAG->ReplaceAllUsesWith(Node, Res);
- CurDAG->RemoveDeadNode(Node);
- }
-
- return Res;
-}
-
void SelectionDAGISel::DoInstructionSelection() {
DEBUG(dbgs() << "===== Instruction selection begins: BB#"
<< FuncInfo->MBB->getNumber()
@@ -992,15 +948,12 @@ void SelectionDAGISel::DoInstructionSelection() {
// If the current node is a strict FP pseudo-op, the isStrictFPOp()
// function will provide the corresponding normal FP opcode to which the
// node should be mutated.
- unsigned NormalFPOpc = ISD::UNDEF;
- bool IsStrictFPOp = isStrictFPOp(Node, NormalFPOpc);
- if (IsStrictFPOp)
- Node = MutateStrictFPToFP(Node, NormalFPOpc);
+ //
+ // FIXME: The backends need a way to handle FP constraints.
+ if (Node->isStrictFPOpcode())
+ Node = CurDAG->mutateStrictFPToFP(Node);
Select(Node);
-
- // FIXME: Add code here to attach an implicit def and use of
- // target-specific FP environment registers.
}
CurDAG->setRoot(Dummy.getValue());
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index befbd80d7965..0dffffee9976 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -603,11 +603,11 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
if (SimplifyDemandedBits(Op.getOperand(0), ~Known.Zero & NewMask,
Known2, TLO, Depth+1))
return true;
- assert((Known2.Zero & Known2.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known2.hasConflict() && "Bits known to be one AND zero?");
// If all of the demanded bits are known one on one side, return the other.
// These bits cannot contribute to the result of the 'and'.
@@ -633,11 +633,11 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
case ISD::OR:
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
if (SimplifyDemandedBits(Op.getOperand(0), ~Known.One & NewMask,
Known2, TLO, Depth+1))
return true;
- assert((Known2.Zero & Known2.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known2.hasConflict() && "Bits known to be one AND zero?");
// If all of the demanded bits are known zero on one side, return the other.
// These bits cannot contribute to the result of the 'or'.
@@ -660,10 +660,10 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
case ISD::XOR: {
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
if (SimplifyDemandedBits(Op.getOperand(0), NewMask, Known2, TLO, Depth+1))
return true;
- assert((Known2.Zero & Known2.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known2.hasConflict() && "Bits known to be one AND zero?");
// If all of the demanded bits are known zero on one side, return the other.
// These bits cannot contribute to the result of the 'xor'.
@@ -725,8 +725,8 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
return true;
if (SimplifyDemandedBits(Op.getOperand(1), NewMask, Known2, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
- assert((Known2.Zero & Known2.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
+ assert(!Known2.hasConflict() && "Bits known to be one AND zero?");
// If the operands are constants, see if we can simplify them.
if (ShrinkDemandedConstant(Op, NewMask, TLO))
@@ -741,8 +741,8 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
return true;
if (SimplifyDemandedBits(Op.getOperand(2), NewMask, Known2, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
- assert((Known2.Zero & Known2.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
+ assert(!Known2.hasConflict() && "Bits known to be one AND zero?");
// If the operands are constants, see if we can simplify them.
if (ShrinkDemandedConstant(Op, NewMask, TLO))
@@ -907,7 +907,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
// Compute the new bits that are at the top now.
if (SimplifyDemandedBits(InOp, InDemandedMask, Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
Known.Zero.lshrInPlace(ShAmt);
Known.One.lshrInPlace(ShAmt);
@@ -947,7 +947,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
if (SimplifyDemandedBits(Op.getOperand(0), InDemandedMask, Known, TLO,
Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
Known.Zero.lshrInPlace(ShAmt);
Known.One.lshrInPlace(ShAmt);
@@ -1029,7 +1029,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
if (SimplifyDemandedBits(Op.getOperand(0), InputDemandedBits,
Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
// If the sign bit of the input is known set or clear, then we know the
// top bits of the result.
@@ -1084,7 +1084,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
if (SimplifyDemandedBits(Op.getOperand(0), InMask, Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
Known = Known.zext(BitWidth);
Known.Zero |= NewBits;
break;
@@ -1134,7 +1134,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
APInt InMask = NewMask.trunc(OperandBitWidth);
if (SimplifyDemandedBits(Op.getOperand(0), InMask, Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
Known = Known.zext(BitWidth);
break;
}
@@ -1193,7 +1193,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
}
}
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
break;
}
case ISD::AssertZext: {
@@ -1205,7 +1205,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
if (SimplifyDemandedBits(Op.getOperand(0), ~InMask | NewMask,
Known, TLO, Depth+1))
return true;
- assert((Known.Zero & Known.One) == 0 && "Bits known to be one AND zero?");
+ assert(!Known.hasConflict() && "Bits known to be one AND zero?");
Known.Zero |= ~InMask;
break;
diff --git a/lib/CodeGen/ShadowStackGCLowering.cpp b/lib/CodeGen/ShadowStackGCLowering.cpp
index ff7d205c1f4c..6750fde57638 100644
--- a/lib/CodeGen/ShadowStackGCLowering.cpp
+++ b/lib/CodeGen/ShadowStackGCLowering.cpp
@@ -27,7 +27,7 @@
using namespace llvm;
-#define DEBUG_TYPE "shadowstackgclowering"
+#define DEBUG_TYPE "shadow-stack-gc-lowering"
namespace {
@@ -66,10 +66,10 @@ private:
};
}
-INITIALIZE_PASS_BEGIN(ShadowStackGCLowering, "shadow-stack-gc-lowering",
+INITIALIZE_PASS_BEGIN(ShadowStackGCLowering, DEBUG_TYPE,
"Shadow Stack GC Lowering", false, false)
INITIALIZE_PASS_DEPENDENCY(GCModuleInfo)
-INITIALIZE_PASS_END(ShadowStackGCLowering, "shadow-stack-gc-lowering",
+INITIALIZE_PASS_END(ShadowStackGCLowering, DEBUG_TYPE,
"Shadow Stack GC Lowering", false, false)
FunctionPass *llvm::createShadowStackGCLoweringPass() { return new ShadowStackGCLowering(); }
diff --git a/lib/CodeGen/ShrinkWrap.cpp b/lib/CodeGen/ShrinkWrap.cpp
index 2638702da152..aa75f5e2caa2 100644
--- a/lib/CodeGen/ShrinkWrap.cpp
+++ b/lib/CodeGen/ShrinkWrap.cpp
@@ -210,13 +210,12 @@ public:
char ShrinkWrap::ID = 0;
char &llvm::ShrinkWrapID = ShrinkWrap::ID;
-INITIALIZE_PASS_BEGIN(ShrinkWrap, "shrink-wrap", "Shrink Wrap Pass", false,
- false)
+INITIALIZE_PASS_BEGIN(ShrinkWrap, DEBUG_TYPE, "Shrink Wrap Pass", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachinePostDominatorTree)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
-INITIALIZE_PASS_END(ShrinkWrap, "shrink-wrap", "Shrink Wrap Pass", false, false)
+INITIALIZE_PASS_END(ShrinkWrap, DEBUG_TYPE, "Shrink Wrap Pass", false, false)
bool ShrinkWrap::useOrDefCSROrFI(const MachineInstr &MI,
RegScavenger *RS) const {
diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp
index e9eff4d0acb2..09e9c3bb3354 100644
--- a/lib/CodeGen/SjLjEHPrepare.cpp
+++ b/lib/CodeGen/SjLjEHPrepare.cpp
@@ -74,7 +74,7 @@ private:
} // end anonymous namespace
char SjLjEHPrepare::ID = 0;
-INITIALIZE_PASS(SjLjEHPrepare, "sjljehprepare", "Prepare SjLj exceptions",
+INITIALIZE_PASS(SjLjEHPrepare, DEBUG_TYPE, "Prepare SjLj exceptions",
false, false)
// Public Interface To the SjLjEHPrepare pass.
diff --git a/lib/CodeGen/SlotIndexes.cpp b/lib/CodeGen/SlotIndexes.cpp
index bc2a1d09056b..3656832a7f1a 100644
--- a/lib/CodeGen/SlotIndexes.cpp
+++ b/lib/CodeGen/SlotIndexes.cpp
@@ -19,7 +19,7 @@ using namespace llvm;
#define DEBUG_TYPE "slotindexes"
char SlotIndexes::ID = 0;
-INITIALIZE_PASS(SlotIndexes, "slotindexes",
+INITIALIZE_PASS(SlotIndexes, DEBUG_TYPE,
"Slot index numbering", false, false)
STATISTIC(NumLocalRenum, "Number of local renumberings");
diff --git a/lib/CodeGen/SpillPlacement.cpp b/lib/CodeGen/SpillPlacement.cpp
index 43cbf4add0f8..0abe1c47da55 100644
--- a/lib/CodeGen/SpillPlacement.cpp
+++ b/lib/CodeGen/SpillPlacement.cpp
@@ -40,14 +40,14 @@
using namespace llvm;
-#define DEBUG_TYPE "spillplacement"
+#define DEBUG_TYPE "spill-code-placement"
char SpillPlacement::ID = 0;
-INITIALIZE_PASS_BEGIN(SpillPlacement, "spill-code-placement",
+INITIALIZE_PASS_BEGIN(SpillPlacement, DEBUG_TYPE,
"Spill Code Placement Analysis", true, true)
INITIALIZE_PASS_DEPENDENCY(EdgeBundles)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
-INITIALIZE_PASS_END(SpillPlacement, "spill-code-placement",
+INITIALIZE_PASS_END(SpillPlacement, DEBUG_TYPE,
"Spill Code Placement Analysis", true, true)
char &llvm::SpillPlacementID = SpillPlacement::ID;
diff --git a/lib/CodeGen/StackColoring.cpp b/lib/CodeGen/StackColoring.cpp
index 86a16187fcb6..acb3676fdd71 100644
--- a/lib/CodeGen/StackColoring.cpp
+++ b/lib/CodeGen/StackColoring.cpp
@@ -53,7 +53,7 @@
using namespace llvm;
-#define DEBUG_TYPE "stackcoloring"
+#define DEBUG_TYPE "stack-coloring"
static cl::opt<bool>
DisableColoring("no-stack-coloring",
@@ -371,12 +371,12 @@ private:
char StackColoring::ID = 0;
char &llvm::StackColoringID = StackColoring::ID;
-INITIALIZE_PASS_BEGIN(StackColoring,
- "stack-coloring", "Merge disjoint stack slots", false, false)
+INITIALIZE_PASS_BEGIN(StackColoring, DEBUG_TYPE,
+ "Merge disjoint stack slots", false, false)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_DEPENDENCY(StackProtector)
-INITIALIZE_PASS_END(StackColoring,
- "stack-coloring", "Merge disjoint stack slots", false, false)
+INITIALIZE_PASS_END(StackColoring, DEBUG_TYPE,
+ "Merge disjoint stack slots", false, false)
void StackColoring::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<SlotIndexes>();
diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp
index 5da77264261b..ca8bde2d114a 100644
--- a/lib/CodeGen/StackProtector.cpp
+++ b/lib/CodeGen/StackProtector.cpp
@@ -58,10 +58,10 @@ static cl::opt<bool> EnableSelectionDAGSP("enable-selectiondag-sp",
cl::init(true), cl::Hidden);
char StackProtector::ID = 0;
-INITIALIZE_PASS_BEGIN(StackProtector, "stack-protector",
+INITIALIZE_PASS_BEGIN(StackProtector, DEBUG_TYPE,
"Insert stack protectors", false, true)
INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
-INITIALIZE_PASS_END(StackProtector, "stack-protector",
+INITIALIZE_PASS_END(StackProtector, DEBUG_TYPE,
"Insert stack protectors", false, true)
FunctionPass *llvm::createStackProtectorPass() { return new StackProtector(); }
diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp
index 234b2043a6a1..d1758ecbd79f 100644
--- a/lib/CodeGen/StackSlotColoring.cpp
+++ b/lib/CodeGen/StackSlotColoring.cpp
@@ -32,7 +32,7 @@
#include <vector>
using namespace llvm;
-#define DEBUG_TYPE "stackslotcoloring"
+#define DEBUG_TYPE "stack-slot-coloring"
static cl::opt<bool>
DisableSharing("no-stack-slot-sharing",
@@ -116,12 +116,12 @@ namespace {
char StackSlotColoring::ID = 0;
char &llvm::StackSlotColoringID = StackSlotColoring::ID;
-INITIALIZE_PASS_BEGIN(StackSlotColoring, "stack-slot-coloring",
+INITIALIZE_PASS_BEGIN(StackSlotColoring, DEBUG_TYPE,
"Stack Slot Coloring", false, false)
INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
INITIALIZE_PASS_DEPENDENCY(LiveStacks)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
-INITIALIZE_PASS_END(StackSlotColoring, "stack-slot-coloring",
+INITIALIZE_PASS_END(StackSlotColoring, DEBUG_TYPE,
"Stack Slot Coloring", false, false)
namespace {
diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp
index e2377d89497d..ad0b04373656 100644
--- a/lib/CodeGen/TailDuplication.cpp
+++ b/lib/CodeGen/TailDuplication.cpp
@@ -40,8 +40,7 @@ char TailDuplicatePass::ID = 0;
char &llvm::TailDuplicateID = TailDuplicatePass::ID;
-INITIALIZE_PASS(TailDuplicatePass, "tailduplication", "Tail Duplication", false,
- false)
+INITIALIZE_PASS(TailDuplicatePass, DEBUG_TYPE, "Tail Duplication", false, false)
bool TailDuplicatePass::runOnMachineFunction(MachineFunction &MF) {
if (skipFunction(*MF.getFunction()))
diff --git a/lib/CodeGen/TailDuplicator.cpp b/lib/CodeGen/TailDuplicator.cpp
index d2414200e9d5..d40f7af431a9 100644
--- a/lib/CodeGen/TailDuplicator.cpp
+++ b/lib/CodeGen/TailDuplicator.cpp
@@ -749,7 +749,7 @@ bool TailDuplicator::canTailDuplicate(MachineBasicBlock *TailBB,
if (PredBB->succ_size() > 1)
return false;
- MachineBasicBlock *PredTBB, *PredFBB;
+ MachineBasicBlock *PredTBB = nullptr, *PredFBB = nullptr;
SmallVector<MachineOperand, 4> PredCond;
if (TII->analyzeBranch(*PredBB, PredTBB, PredFBB, PredCond))
return false;
@@ -832,7 +832,7 @@ bool TailDuplicator::tailDuplicate(bool IsSimple, MachineBasicBlock *TailBB,
appendCopies(PredBB, CopyInfos, Copies);
// Simplify
- MachineBasicBlock *PredTBB, *PredFBB;
+ MachineBasicBlock *PredTBB = nullptr, *PredFBB = nullptr;
SmallVector<MachineOperand, 4> PredCond;
TII->analyzeBranch(*PredBB, PredTBB, PredFBB, PredCond);
diff --git a/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp
index 7392c8327148..552a89f76ca2 100644
--- a/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -52,7 +52,7 @@
using namespace llvm;
-#define DEBUG_TYPE "twoaddrinstr"
+#define DEBUG_TYPE "twoaddressinstruction"
STATISTIC(NumTwoAddressInstrs, "Number of two-address instructions");
STATISTIC(NumCommuted , "Number of instructions commuted to coalesce");
@@ -171,10 +171,10 @@ public:
} // end anonymous namespace
char TwoAddressInstructionPass::ID = 0;
-INITIALIZE_PASS_BEGIN(TwoAddressInstructionPass, "twoaddressinstruction",
+INITIALIZE_PASS_BEGIN(TwoAddressInstructionPass, DEBUG_TYPE,
"Two-Address instruction pass", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
-INITIALIZE_PASS_END(TwoAddressInstructionPass, "twoaddressinstruction",
+INITIALIZE_PASS_END(TwoAddressInstructionPass, DEBUG_TYPE,
"Two-Address instruction pass", false, false)
char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionPass::ID;
diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp
index a632b40c20f5..4e7542bf31e0 100644
--- a/lib/CodeGen/WinEHPrepare.cpp
+++ b/lib/CodeGen/WinEHPrepare.cpp
@@ -94,7 +94,7 @@ private:
} // end anonymous namespace
char WinEHPrepare::ID = 0;
-INITIALIZE_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",
+INITIALIZE_PASS(WinEHPrepare, DEBUG_TYPE, "Prepare Windows exceptions",
false, false)
FunctionPass *llvm::createWinEHPass() { return new WinEHPrepare(); }
diff --git a/lib/DebugInfo/CodeView/CMakeLists.txt b/lib/DebugInfo/CodeView/CMakeLists.txt
index 556ebf78622f..90193d07b95d 100644
--- a/lib/DebugInfo/CodeView/CMakeLists.txt
+++ b/lib/DebugInfo/CodeView/CMakeLists.txt
@@ -22,6 +22,7 @@ add_llvm_library(LLVMDebugInfoCodeView
TypeDatabaseVisitor.cpp
TypeDumpVisitor.cpp
TypeIndex.cpp
+ TypeIndexDiscovery.cpp
TypeRecordMapping.cpp
TypeSerializer.cpp
TypeStreamMerger.cpp
diff --git a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index f95c3e79388e..705b548141b0 100644
--- a/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -45,24 +45,9 @@ static Error visitKnownMember(CVMemberRecord &Record,
}
static Expected<TypeServer2Record> deserializeTypeServerRecord(CVType &Record) {
- class StealTypeServerVisitor : public TypeVisitorCallbacks {
- public:
- explicit StealTypeServerVisitor(TypeServer2Record &TR) : TR(TR) {}
-
- Error visitKnownRecord(CVType &CVR, TypeServer2Record &Record) override {
- TR = Record;
- return Error::success();
- }
-
- private:
- TypeServer2Record &TR;
- };
-
TypeServer2Record R(TypeRecordKind::TypeServer2);
- StealTypeServerVisitor Thief(R);
- if (auto EC = visitTypeRecord(Record, Thief))
+ if (auto EC = TypeDeserializer::deserializeAs(Record, R))
return std::move(EC);
-
return R;
}
@@ -308,8 +293,9 @@ Error llvm::codeview::visitTypeRecord(CVType &Record,
Error llvm::codeview::visitTypeStream(const CVTypeArray &Types,
TypeVisitorCallbacks &Callbacks,
+ VisitorDataSource Source,
TypeServerHandler *TS) {
- VisitHelper V(Callbacks, VDS_BytesPresent);
+ VisitHelper V(Callbacks, Source);
if (TS)
V.Visitor.addTypeServerHandler(*TS);
return V.Visitor.visitTypeStream(Types);
diff --git a/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
new file mode 100644
index 000000000000..11e2e215303c
--- /dev/null
+++ b/lib/DebugInfo/CodeView/TypeIndexDiscovery.cpp
@@ -0,0 +1,371 @@
+//===- TypeIndexDiscovery.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/TypeIndexDiscovery.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+static inline MethodKind getMethodKind(uint16_t Attrs) {
+ Attrs &= uint16_t(MethodOptions::MethodKindMask);
+ Attrs >>= 2;
+ return MethodKind(Attrs);
+}
+
+static inline bool isIntroVirtual(uint16_t Attrs) {
+ MethodKind MK = getMethodKind(Attrs);
+ return MK == MethodKind::IntroducingVirtual ||
+ MK == MethodKind::PureIntroducingVirtual;
+}
+
+static inline PointerMode getPointerMode(uint32_t Attrs) {
+ return static_cast<PointerMode>((Attrs >> PointerRecord::PointerModeShift) &
+ PointerRecord::PointerModeMask);
+}
+
+static inline bool isMemberPointer(uint32_t Attrs) {
+ PointerMode Mode = getPointerMode(Attrs);
+ return Mode == PointerMode::PointerToDataMember ||
+ Mode == PointerMode::PointerToDataMember;
+}
+
+static inline uint32_t getEncodedIntegerLength(ArrayRef<uint8_t> Data) {
+ uint16_t N = support::endian::read16le(Data.data());
+ if (N < LF_NUMERIC)
+ return 2;
+
+ assert(N <= LF_UQUADWORD);
+
+ constexpr uint32_t Sizes[] = {
+ 1, // LF_CHAR
+ 2, // LF_SHORT
+ 2, // LF_USHORT
+ 4, // LF_LONG
+ 4, // LF_ULONG
+ 4, // LF_REAL32
+ 8, // LF_REAL64
+ 10, // LF_REAL80
+ 16, // LF_REAL128
+ 8, // LF_QUADWORD
+ 8, // LF_UQUADWORD
+ };
+
+ return Sizes[N - LF_NUMERIC];
+}
+
+static inline uint32_t getCStringLength(ArrayRef<uint8_t> Data) {
+ const char *S = reinterpret_cast<const char *>(Data.data());
+ return strlen(S) + 1;
+}
+
+static void handleMethodOverloadList(ArrayRef<uint8_t> Content,
+ SmallVectorImpl<TiReference> &Refs) {
+ uint32_t Offset = 0;
+
+ while (!Content.empty()) {
+ // Array of:
+ // 0: Attrs
+ // 2: Padding
+ // 4: TypeIndex
+ // if (isIntroVirtual())
+ // 8: VFTableOffset
+
+ // At least 8 bytes are guaranteed. 4 extra bytes come iff function is an
+ // intro virtual.
+ uint32_t Len = 8;
+
+ uint16_t Attrs = support::endian::read16le(Content.data());
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+
+ if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
+ Len += 4;
+ Offset += Len;
+ Content = Content.drop_front(Len);
+ }
+}
+
+static uint32_t handleBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: TypeIndex
+ // 8: Encoded Integer
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+ return 8 + getEncodedIntegerLength(Data.drop_front(8));
+}
+
+static uint32_t handleEnumerator(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: Encoded Integer
+ // <next>: Name
+ uint32_t Size = 4 + getEncodedIntegerLength(Data.drop_front(4));
+ return Size + getCStringLength(Data.drop_front(Size));
+}
+
+static uint32_t handleDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: TypeIndex
+ // 8: Encoded Integer
+ // <next>: Name
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+ uint32_t Size = 8 + getEncodedIntegerLength(Data.drop_front(8));
+ return Size + getCStringLength(Data.drop_front(Size));
+}
+
+static uint32_t handleOverloadedMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: TypeIndex
+ // 8: Name
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+ return 8 + getCStringLength(Data.drop_front(8));
+}
+
+static uint32_t handleOneMethod(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Attributes
+ // 4: Type
+ // if (isIntroVirtual)
+ // 8: VFTableOffset
+ // <next>: Name
+ uint32_t Size = 8;
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+
+ uint16_t Attrs = support::endian::read16le(Data.drop_front(2).data());
+ if (LLVM_UNLIKELY(isIntroVirtual(Attrs)))
+ Size += 4;
+
+ return Size + getCStringLength(Data.drop_front(Size));
+}
+
+static uint32_t handleNestedType(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: TypeIndex
+ // 8: Name
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+ return 8 + getCStringLength(Data.drop_front(8));
+}
+
+static uint32_t handleStaticDataMember(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: TypeIndex
+ // 8: Name
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+ return 8 + getCStringLength(Data.drop_front(8));
+}
+
+static uint32_t handleVirtualBaseClass(ArrayRef<uint8_t> Data, uint32_t Offset,
+ bool IsIndirect,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Attrs
+ // 4: TypeIndex
+ // 8: TypeIndex
+ // 12: Encoded Integer
+ // <next>: Encoded Integer
+ uint32_t Size = 12;
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 2});
+ Size += getEncodedIntegerLength(Data.drop_front(Size));
+ Size += getEncodedIntegerLength(Data.drop_front(Size));
+ return Size;
+}
+
+static uint32_t handleVFPtr(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: TypeIndex
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+ return 8;
+}
+
+static uint32_t handleListContinuation(ArrayRef<uint8_t> Data, uint32_t Offset,
+ SmallVectorImpl<TiReference> &Refs) {
+ // 0: Kind
+ // 2: Padding
+ // 4: TypeIndex
+ Refs.push_back({TiRefKind::TypeRef, Offset + 4, 1});
+ return 8;
+}
+
+static void handleFieldList(ArrayRef<uint8_t> Content,
+ SmallVectorImpl<TiReference> &Refs) {
+ uint32_t Offset = 0;
+ uint32_t ThisLen = 0;
+ while (!Content.empty()) {
+ TypeLeafKind Kind =
+ static_cast<TypeLeafKind>(support::endian::read16le(Content.data()));
+ switch (Kind) {
+ case LF_BCLASS:
+ ThisLen = handleBaseClass(Content, Offset, Refs);
+ break;
+ case LF_ENUMERATE:
+ ThisLen = handleEnumerator(Content, Offset, Refs);
+ break;
+ case LF_MEMBER:
+ ThisLen = handleDataMember(Content, Offset, Refs);
+ break;
+ case LF_METHOD:
+ ThisLen = handleOverloadedMethod(Content, Offset, Refs);
+ break;
+ case LF_ONEMETHOD:
+ ThisLen = handleOneMethod(Content, Offset, Refs);
+ break;
+ case LF_NESTTYPE:
+ ThisLen = handleNestedType(Content, Offset, Refs);
+ break;
+ case LF_STMEMBER:
+ ThisLen = handleStaticDataMember(Content, Offset, Refs);
+ break;
+ case LF_VBCLASS:
+ case LF_IVBCLASS:
+ ThisLen =
+ handleVirtualBaseClass(Content, Offset, Kind == LF_VBCLASS, Refs);
+ break;
+ case LF_VFUNCTAB:
+ ThisLen = handleVFPtr(Content, Offset, Refs);
+ break;
+ case LF_INDEX:
+ ThisLen = handleListContinuation(Content, Offset, Refs);
+ break;
+ default:
+ return;
+ }
+ Content = Content.drop_front(ThisLen);
+ Offset += ThisLen;
+ if (!Content.empty()) {
+ uint8_t Pad = Content.front();
+ if (Pad >= LF_PAD0) {
+ uint32_t Skip = Pad & 0x0F;
+ Content = Content.drop_front(Skip);
+ Offset += Skip;
+ }
+ }
+ }
+}
+
+static void handlePointer(ArrayRef<uint8_t> Content,
+ SmallVectorImpl<TiReference> &Refs) {
+ Refs.push_back({TiRefKind::TypeRef, 0, 1});
+
+ uint32_t Attrs = support::endian::read32le(Content.drop_front(4).data());
+ if (isMemberPointer(Attrs))
+ Refs.push_back({TiRefKind::TypeRef, 8, 1});
+}
+
+static void discoverTypeIndices(ArrayRef<uint8_t> Content, TypeLeafKind Kind,
+ SmallVectorImpl<TiReference> &Refs) {
+ uint32_t Count;
+ // FIXME: In the future it would be nice if we could avoid hardcoding these
+ // values. One idea is to define some structures representing these types
+ // that would allow the use of offsetof().
+ switch (Kind) {
+ case TypeLeafKind::LF_FUNC_ID:
+ Refs.push_back({TiRefKind::IndexRef, 0, 1});
+ Refs.push_back({TiRefKind::TypeRef, 4, 1});
+ break;
+ case TypeLeafKind::LF_MFUNC_ID:
+ Refs.push_back({TiRefKind::TypeRef, 0, 2});
+ break;
+ case TypeLeafKind::LF_STRING_ID:
+ Refs.push_back({TiRefKind::IndexRef, 0, 1});
+ break;
+ case TypeLeafKind::LF_SUBSTR_LIST:
+ Count = support::endian::read32le(Content.data());
+ if (Count > 0)
+ Refs.push_back({TiRefKind::IndexRef, 4, Count});
+ break;
+ case TypeLeafKind::LF_BUILDINFO:
+ Count = support::endian::read16le(Content.data());
+ if (Count > 0)
+ Refs.push_back({TiRefKind::IndexRef, 2, Count});
+ break;
+ case TypeLeafKind::LF_UDT_SRC_LINE:
+ Refs.push_back({TiRefKind::TypeRef, 0, 1});
+ Refs.push_back({TiRefKind::IndexRef, 4, 1});
+ break;
+ case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
+ Refs.push_back({TiRefKind::TypeRef, 0, 1});
+ break;
+ case TypeLeafKind::LF_MODIFIER:
+ Refs.push_back({TiRefKind::TypeRef, 0, 1});
+ break;
+ case TypeLeafKind::LF_PROCEDURE:
+ Refs.push_back({TiRefKind::TypeRef, 0, 1});
+ Refs.push_back({TiRefKind::TypeRef, 8, 1});
+ break;
+ case TypeLeafKind::LF_MFUNCTION:
+ Refs.push_back({TiRefKind::TypeRef, 0, 3});
+ Refs.push_back({TiRefKind::TypeRef, 16, 1});
+ break;
+ case TypeLeafKind::LF_ARGLIST:
+ Count = support::endian::read32le(Content.data());
+ if (Count > 0)
+ Refs.push_back({TiRefKind::TypeRef, 4, Count});
+ break;
+ case TypeLeafKind::LF_ARRAY:
+ Refs.push_back({TiRefKind::TypeRef, 0, 2});
+ break;
+ case TypeLeafKind::LF_CLASS:
+ case TypeLeafKind::LF_STRUCTURE:
+ case TypeLeafKind::LF_INTERFACE:
+ Refs.push_back({TiRefKind::TypeRef, 4, 3});
+ break;
+ case TypeLeafKind::LF_UNION:
+ Refs.push_back({TiRefKind::TypeRef, 4, 1});
+ break;
+ case TypeLeafKind::LF_ENUM:
+ Refs.push_back({TiRefKind::TypeRef, 4, 2});
+ break;
+ case TypeLeafKind::LF_BITFIELD:
+ Refs.push_back({TiRefKind::TypeRef, 0, 1});
+ break;
+ case TypeLeafKind::LF_VFTABLE:
+ Refs.push_back({TiRefKind::TypeRef, 0, 2});
+ break;
+ case TypeLeafKind::LF_VTSHAPE:
+ break;
+ case TypeLeafKind::LF_METHODLIST:
+ handleMethodOverloadList(Content, Refs);
+ break;
+ case TypeLeafKind::LF_FIELDLIST:
+ handleFieldList(Content, Refs);
+ break;
+ case TypeLeafKind::LF_POINTER:
+ handlePointer(Content, Refs);
+ break;
+ default:
+ break;
+ }
+}
+
+void llvm::codeview::discoverTypeIndices(const CVType &Type,
+ SmallVectorImpl<TiReference> &Refs) {
+ ::discoverTypeIndices(Type.content(), Type.kind(), Refs);
+}
+
+void llvm::codeview::discoverTypeIndices(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TiReference> &Refs) {
+ const RecordPrefix *P =
+ reinterpret_cast<const RecordPrefix *>(RecordData.data());
+ TypeLeafKind K = static_cast<TypeLeafKind>(uint16_t(P->RecordKind));
+ ::discoverTypeIndices(RecordData.drop_front(sizeof(RecordPrefix)), K, Refs);
+}
diff --git a/lib/DebugInfo/CodeView/TypeSerializer.cpp b/lib/DebugInfo/CodeView/TypeSerializer.cpp
index 3b061e67e05e..93c1198e36ce 100644
--- a/lib/DebugInfo/CodeView/TypeSerializer.cpp
+++ b/lib/DebugInfo/CodeView/TypeSerializer.cpp
@@ -9,6 +9,7 @@
#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include <string.h>
@@ -16,21 +17,109 @@
using namespace llvm;
using namespace llvm::codeview;
-bool TypeSerializer::isInFieldList() const {
- return TypeKind.hasValue() && *TypeKind == TypeLeafKind::LF_FIELDLIST;
+namespace {
+struct HashedType {
+ uint64_t Hash;
+ const uint8_t *Data;
+ unsigned Size; // FIXME: Go to uint16_t?
+ TypeIndex Index;
+};
+
+/// Wrapper around a poitner to a HashedType. Hash and equality operations are
+/// based on data in the pointee.
+struct HashedTypePtr {
+ HashedTypePtr() = default;
+ HashedTypePtr(HashedType *Ptr) : Ptr(Ptr) {}
+ HashedType *Ptr = nullptr;
+};
+} // namespace
+
+namespace llvm {
+template <> struct DenseMapInfo<HashedTypePtr> {
+ static inline HashedTypePtr getEmptyKey() { return HashedTypePtr(nullptr); }
+ static inline HashedTypePtr getTombstoneKey() {
+ return HashedTypePtr(reinterpret_cast<HashedType *>(1));
+ }
+ static unsigned getHashValue(HashedTypePtr Val) {
+ assert(Val.Ptr != getEmptyKey().Ptr && Val.Ptr != getTombstoneKey().Ptr);
+ return Val.Ptr->Hash;
+ }
+ static bool isEqual(HashedTypePtr LHSP, HashedTypePtr RHSP) {
+ HashedType *LHS = LHSP.Ptr;
+ HashedType *RHS = RHSP.Ptr;
+ if (RHS == getEmptyKey().Ptr || RHS == getTombstoneKey().Ptr)
+ return LHS == RHS;
+ if (LHS->Hash != RHS->Hash || LHS->Size != RHS->Size)
+ return false;
+ return ::memcmp(LHS->Data, RHS->Data, LHS->Size) == 0;
+ }
+};
}
-TypeIndex TypeSerializer::calcNextTypeIndex() const {
- if (LastTypeIndex.isNoneType())
- return TypeIndex(TypeIndex::FirstNonSimpleIndex);
- else
- return TypeIndex(LastTypeIndex.getIndex() + 1);
+/// Private implementation so that we don't leak our DenseMap instantiations to
+/// users.
+class llvm::codeview::TypeHasher {
+private:
+ /// Storage for type record provided by the caller. Records will outlive the
+ /// hasher object, so they should be allocated here.
+ BumpPtrAllocator &RecordStorage;
+
+ /// Storage for hash keys. These only need to live as long as the hashing
+ /// operation.
+ BumpPtrAllocator KeyStorage;
+
+ /// Hash table. We really want a DenseMap<ArrayRef<uint8_t>, TypeIndex> here,
+ /// but DenseMap is inefficient when the keys are long (like type records)
+ /// because it recomputes the hash value of every key when it grows. This
+ /// value type stores the hash out of line in KeyStorage, so that table
+ /// entries are small and easy to rehash.
+ DenseSet<HashedTypePtr> HashedRecords;
+
+public:
+ TypeHasher(BumpPtrAllocator &RecordStorage) : RecordStorage(RecordStorage) {}
+
+ void reset() { HashedRecords.clear(); }
+
+ /// Takes the bytes of type record, inserts them into the hash table, saves
+ /// them, and returns a pointer to an identical stable type record along with
+ /// its type index in the destination stream.
+ TypeIndex getOrCreateRecord(ArrayRef<uint8_t> &Record, TypeIndex TI);
+};
+
+TypeIndex TypeHasher::getOrCreateRecord(ArrayRef<uint8_t> &Record,
+ TypeIndex TI) {
+ assert(Record.size() < UINT32_MAX && "Record too big");
+ assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
+
+ // Compute the hash up front so we can store it in the key.
+ HashedType TempHashedType = {hash_value(Record), Record.data(),
+ unsigned(Record.size()), TI};
+ auto Result = HashedRecords.insert(HashedTypePtr(&TempHashedType));
+ HashedType *&Hashed = Result.first->Ptr;
+
+ if (Result.second) {
+ // This was a new type record. We need stable storage for both the key and
+ // the record. The record should outlive the hashing operation.
+ Hashed = KeyStorage.Allocate<HashedType>();
+ *Hashed = TempHashedType;
+
+ uint8_t *Stable = RecordStorage.Allocate<uint8_t>(Record.size());
+ memcpy(Stable, Record.data(), Record.size());
+ Hashed->Data = Stable;
+ assert(Hashed->Size == Record.size());
+ }
+
+ // Update the caller's copy of Record to point a stable copy.
+ Record = ArrayRef<uint8_t>(Hashed->Data, Hashed->Size);
+ return Hashed->Index;
}
-TypeIndex TypeSerializer::incrementTypeIndex() {
- TypeIndex Previous = LastTypeIndex;
- LastTypeIndex = calcNextTypeIndex();
- return Previous;
+TypeIndex TypeSerializer::nextTypeIndex() const {
+ return TypeIndex::fromArrayIndex(SeenRecords.size());
+}
+
+bool TypeSerializer::isInFieldList() const {
+ return TypeKind.hasValue() && *TypeKind == TypeLeafKind::LF_FIELDLIST;
}
MutableArrayRef<uint8_t> TypeSerializer::getCurrentSubRecordData() {
@@ -51,46 +140,6 @@ Error TypeSerializer::writeRecordPrefix(TypeLeafKind Kind) {
return Error::success();
}
-TypeIndex
-TypeSerializer::insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record) {
- assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
-
- StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size());
-
- TypeIndex NextTypeIndex = calcNextTypeIndex();
- auto Result = HashedRecords.try_emplace(S, NextTypeIndex);
- if (Result.second) {
- LastTypeIndex = NextTypeIndex;
- SeenRecords.push_back(Record);
- }
- return Result.first->getValue();
-}
-
-TypeIndex
-TypeSerializer::insertRecordBytesWithCopy(CVType &Record,
- MutableArrayRef<uint8_t> Data) {
- assert(Data.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
-
- StringRef S(reinterpret_cast<const char *>(Data.data()), Data.size());
-
- // Do a two state lookup / insert so that we don't have to allocate unless
- // we're going
- // to do an insert. This is a big memory savings.
- auto Iter = HashedRecords.find(S);
- if (Iter != HashedRecords.end())
- return Iter->second;
-
- LastTypeIndex = calcNextTypeIndex();
- uint8_t *Copy = RecordStorage.Allocate<uint8_t>(Data.size());
- ::memcpy(Copy, Data.data(), Data.size());
- Data = MutableArrayRef<uint8_t>(Copy, Data.size());
- S = StringRef(reinterpret_cast<const char *>(Data.data()), Data.size());
- HashedRecords.insert(std::make_pair(S, LastTypeIndex));
- SeenRecords.push_back(Data);
- Record.RecordData = Data;
- return LastTypeIndex;
-}
-
Expected<MutableArrayRef<uint8_t>>
TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
uint32_t Align = Record.size() % 4;
@@ -108,27 +157,79 @@ TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
return MutableArrayRef<uint8_t>(Record.data(), Record.size() + N);
}
-TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage)
- : RecordStorage(Storage), LastTypeIndex(),
- RecordBuffer(MaxRecordLength * 2),
+TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage, bool Hash)
+ : RecordStorage(Storage), RecordBuffer(MaxRecordLength * 2),
Stream(RecordBuffer, llvm::support::little), Writer(Stream),
Mapping(Writer) {
// RecordBuffer needs to be able to hold enough data so that if we are 1
// byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes,
// we won't overflow.
+ if (Hash)
+ Hasher = make_unique<TypeHasher>(Storage);
}
-ArrayRef<MutableArrayRef<uint8_t>> TypeSerializer::records() const {
+TypeSerializer::~TypeSerializer() = default;
+
+ArrayRef<ArrayRef<uint8_t>> TypeSerializer::records() const {
return SeenRecords;
}
-TypeIndex TypeSerializer::getLastTypeIndex() const { return LastTypeIndex; }
+void TypeSerializer::reset() {
+ if (Hasher)
+ Hasher->reset();
+ Writer.setOffset(0);
+ CurrentSegment = RecordSegment();
+ FieldListSegments.clear();
+ TypeKind.reset();
+ MemberKind.reset();
+ SeenRecords.clear();
+}
-TypeIndex TypeSerializer::insertRecordBytes(MutableArrayRef<uint8_t> Record) {
+TypeIndex TypeSerializer::insertRecordBytes(ArrayRef<uint8_t> &Record) {
assert(!TypeKind.hasValue() && "Already in a type mapping!");
assert(Writer.getOffset() == 0 && "Stream has data already!");
- return insertRecordBytesPrivate(Record);
+ if (Hasher) {
+ TypeIndex ActualTI = Hasher->getOrCreateRecord(Record, nextTypeIndex());
+ if (nextTypeIndex() == ActualTI)
+ SeenRecords.push_back(Record);
+ return ActualTI;
+ }
+
+ TypeIndex NewTI = nextTypeIndex();
+ uint8_t *Stable = RecordStorage.Allocate<uint8_t>(Record.size());
+ memcpy(Stable, Record.data(), Record.size());
+ Record = ArrayRef<uint8_t>(Stable, Record.size());
+ SeenRecords.push_back(Record);
+ return NewTI;
+}
+
+TypeIndex TypeSerializer::insertRecord(const RemappedType &Record) {
+ assert(!TypeKind.hasValue() && "Already in a type mapping!");
+ assert(Writer.getOffset() == 0 && "Stream has data already!");
+
+ TypeIndex TI;
+ ArrayRef<uint8_t> OriginalData = Record.OriginalRecord.RecordData;
+ if (Record.Mappings.empty()) {
+ // This record did not remap any type indices. Just write it.
+ return insertRecordBytes(OriginalData);
+ }
+
+ // At least one type index was remapped. Before we can hash it we have to
+ // copy the full record bytes, re-write each type index, then hash the copy.
+ // We do this in temporary storage since only the DenseMap can decide whether
+ // this record already exists, and if it does we don't want the memory to
+ // stick around.
+ RemapStorage.resize(OriginalData.size());
+ ::memcpy(&RemapStorage[0], OriginalData.data(), OriginalData.size());
+ uint8_t *ContentBegin = RemapStorage.data() + sizeof(RecordPrefix);
+ for (const auto &M : Record.Mappings) {
+ // First 4 bytes of every record are the record prefix, but the mapping
+ // offset is relative to the content which starts after.
+ *(TypeIndex *)(ContentBegin + M.first) = M.second;
+ }
+ auto RemapRef = makeArrayRef(RemapStorage);
+ return insertRecordBytes(RemapRef);
}
Error TypeSerializer::visitTypeBegin(CVType &Record) {
@@ -163,8 +264,13 @@ Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) {
Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t);
Record.Type = *TypeKind;
- TypeIndex InsertedTypeIndex =
- insertRecordBytesWithCopy(Record, ThisRecordData);
+ Record.RecordData = ThisRecordData;
+
+ // insertRecordBytes assumes we're not in a mapping, so do this first.
+ TypeKind.reset();
+ Writer.setOffset(0);
+
+ TypeIndex InsertedTypeIndex = insertRecordBytes(Record.RecordData);
// Write out each additional segment in reverse order, and update each
// record's continuation index to point to the previous one.
@@ -174,11 +280,9 @@ Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) {
reinterpret_cast<support::ulittle32_t *>(CIBytes.data());
assert(*CI == 0xB0C0B0C0 && "Invalid TypeIndex placeholder");
*CI = InsertedTypeIndex.getIndex();
- InsertedTypeIndex = insertRecordBytesPrivate(X);
+ InsertedTypeIndex = insertRecordBytes(X);
}
- TypeKind.reset();
- Writer.setOffset(0);
FieldListSegments.clear();
CurrentSegment.SubRecords.clear();
diff --git a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 46747f8eab99..71a0966df036 100644
--- a/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -11,7 +11,9 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@@ -57,37 +59,56 @@ namespace {
/// looking at the record kind.
class TypeStreamMerger : public TypeVisitorCallbacks {
public:
- TypeStreamMerger(TypeTableBuilder &DestIdStream,
- TypeTableBuilder &DestTypeStream,
- SmallVectorImpl<TypeIndex> &SourceToDest,
- TypeServerHandler *Handler)
- : DestIdStream(DestIdStream), DestTypeStream(DestTypeStream),
- FieldListBuilder(DestTypeStream), Handler(Handler),
- IndexMap(SourceToDest) {}
+ explicit TypeStreamMerger(SmallVectorImpl<TypeIndex> &SourceToDest,
+ TypeServerHandler *Handler)
+ : Handler(Handler), IndexMap(SourceToDest) {
+ SourceToDest.clear();
+ }
static const TypeIndex Untranslated;
-/// TypeVisitorCallbacks overrides.
-#define TYPE_RECORD(EnumName, EnumVal, Name) \
- Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-
- Error visitUnknownType(CVType &Record) override;
-
Error visitTypeBegin(CVType &Record) override;
Error visitTypeEnd(CVType &Record) override;
- Error visitMemberEnd(CVMemberRecord &Record) override;
- Error mergeStream(const CVTypeArray &Types);
+ Error mergeTypesAndIds(TypeTableBuilder &DestIds, TypeTableBuilder &DestTypes,
+ const CVTypeArray &IdsAndTypes);
+ Error mergeIdRecords(TypeTableBuilder &Dest,
+ ArrayRef<TypeIndex> TypeSourceToDest,
+ const CVTypeArray &Ids);
+ Error mergeTypeRecords(TypeTableBuilder &Dest, const CVTypeArray &Types);
private:
+ Error doit(const CVTypeArray &Types);
+
void addMapping(TypeIndex Idx);
- bool remapIndex(TypeIndex &Idx);
+ bool remapTypeIndex(TypeIndex &Idx);
+ bool remapItemIndex(TypeIndex &Idx);
+
+ bool remapIndices(RemappedType &Record, ArrayRef<TiReference> Refs) {
+ auto OriginalData = Record.OriginalRecord.content();
+ bool Success = true;
+ for (auto &Ref : Refs) {
+ uint32_t Offset = Ref.Offset;
+ ArrayRef<uint8_t> Bytes =
+ OriginalData.slice(Ref.Offset, sizeof(TypeIndex));
+ ArrayRef<TypeIndex> TIs(reinterpret_cast<const TypeIndex *>(Bytes.data()),
+ Ref.Count);
+ for (auto TI : TIs) {
+ TypeIndex NewTI = TI;
+ bool ThisSuccess = (Ref.Kind == TiRefKind::IndexRef)
+ ? remapItemIndex(NewTI)
+ : remapTypeIndex(NewTI);
+ if (ThisSuccess && NewTI != TI)
+ Record.Mappings.emplace_back(Offset, NewTI);
+ Offset += sizeof(TypeIndex);
+ Success &= ThisSuccess;
+ }
+ }
+ return Success;
+ }
+
+ bool remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map);
size_t slotForIndex(TypeIndex Idx) const {
assert(!Idx.isSimple() && "simple type indices have no slots");
@@ -98,49 +119,45 @@ private:
return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
}
- template <typename RecordType>
- Error writeRecord(RecordType &R, bool RemapSuccess) {
+ Error writeRecord(TypeTableBuilder &Dest, const RemappedType &Record,
+ bool RemapSuccess) {
TypeIndex DestIdx = Untranslated;
if (RemapSuccess)
- DestIdx = DestTypeStream.writeKnownType(R);
+ DestIdx = Dest.writeSerializedRecord(Record);
addMapping(DestIdx);
return Error::success();
}
- template <typename RecordType>
- Error writeIdRecord(RecordType &R, bool RemapSuccess) {
- TypeIndex DestIdx = Untranslated;
- if (RemapSuccess)
- DestIdx = DestIdStream.writeKnownType(R);
+ Error writeTypeRecord(const CVType &Record) {
+ TypeIndex DestIdx =
+ DestTypeStream->writeSerializedRecord(Record.RecordData);
addMapping(DestIdx);
return Error::success();
}
- template <typename RecordType>
- Error writeMember(RecordType &R, bool RemapSuccess) {
- if (RemapSuccess)
- FieldListBuilder.writeMemberType(R);
- else
- HadUntranslatedMember = true;
- return Error::success();
+ Error writeTypeRecord(const RemappedType &Record, bool RemapSuccess) {
+ return writeRecord(*DestTypeStream, Record, RemapSuccess);
+ }
+
+ Error writeIdRecord(const RemappedType &Record, bool RemapSuccess) {
+ return writeRecord(*DestIdStream, Record, RemapSuccess);
}
Optional<Error> LastError;
bool IsSecondPass = false;
- bool HadUntranslatedMember = false;
-
unsigned NumBadIndices = 0;
- BumpPtrAllocator Allocator;
+ TypeIndex CurIndex{TypeIndex::FirstNonSimpleIndex};
- TypeTableBuilder &DestIdStream;
- TypeTableBuilder &DestTypeStream;
- FieldListRecordBuilder FieldListBuilder;
- TypeServerHandler *Handler;
+ TypeTableBuilder *DestIdStream = nullptr;
+ TypeTableBuilder *DestTypeStream = nullptr;
+ TypeServerHandler *Handler = nullptr;
- TypeIndex CurIndex{TypeIndex::FirstNonSimpleIndex};
+ // If we're only mapping id records, this array contains the mapping for
+ // type records.
+ ArrayRef<TypeIndex> TypeLookup;
/// Map from source type index to destination type index. Indexed by source
/// type index minus 0x1000.
@@ -151,22 +168,34 @@ private:
const TypeIndex TypeStreamMerger::Untranslated(SimpleTypeKind::NotTranslated);
-Error TypeStreamMerger::visitTypeBegin(CVRecord<TypeLeafKind> &Rec) {
+Error TypeStreamMerger::visitTypeBegin(CVType &Rec) {
+ RemappedType R(Rec);
+ SmallVector<TiReference, 32> Refs;
+ discoverTypeIndices(Rec.RecordData, Refs);
+ bool Success = remapIndices(R, Refs);
+ switch (Rec.kind()) {
+ case TypeLeafKind::LF_FUNC_ID:
+ case TypeLeafKind::LF_MFUNC_ID:
+ case TypeLeafKind::LF_STRING_ID:
+ case TypeLeafKind::LF_SUBSTR_LIST:
+ case TypeLeafKind::LF_BUILDINFO:
+ case TypeLeafKind::LF_UDT_SRC_LINE:
+ case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
+ return writeIdRecord(R, Success);
+ default:
+ return writeTypeRecord(R, Success);
+ }
return Error::success();
}
-Error TypeStreamMerger::visitTypeEnd(CVRecord<TypeLeafKind> &Rec) {
- CurIndex = TypeIndex(CurIndex.getIndex() + 1);
+Error TypeStreamMerger::visitTypeEnd(CVType &Rec) {
+ ++CurIndex;
if (!IsSecondPass)
assert(IndexMap.size() == slotForIndex(CurIndex) &&
"visitKnownRecord should add one index map entry");
return Error::success();
}
-Error TypeStreamMerger::visitMemberEnd(CVMemberRecord &Rec) {
- return Error::success();
-}
-
void TypeStreamMerger::addMapping(TypeIndex Idx) {
if (!IsSecondPass) {
assert(IndexMap.size() == slotForIndex(CurIndex) &&
@@ -178,7 +207,7 @@ void TypeStreamMerger::addMapping(TypeIndex Idx) {
}
}
-bool TypeStreamMerger::remapIndex(TypeIndex &Idx) {
+bool TypeStreamMerger::remapIndex(TypeIndex &Idx, ArrayRef<TypeIndex> Map) {
// Simple types are unchanged.
if (Idx.isSimple())
return true;
@@ -187,14 +216,14 @@ bool TypeStreamMerger::remapIndex(TypeIndex &Idx) {
// successfully. If it refers to a type later in the stream or a record we
// had to defer, defer it until later pass.
unsigned MapPos = slotForIndex(Idx);
- if (MapPos < IndexMap.size() && IndexMap[MapPos] != Untranslated) {
- Idx = IndexMap[MapPos];
+ if (MapPos < Map.size() && Map[MapPos] != Untranslated) {
+ Idx = Map[MapPos];
return true;
}
// If this is the second pass and this index isn't in the map, then it points
// outside the current type stream, and this is a corrupt record.
- if (IsSecondPass && MapPos >= IndexMap.size()) {
+ if (IsSecondPass && MapPos >= Map.size()) {
// FIXME: Print a more useful error. We can give the current record and the
// index that we think its pointing to.
LastError = joinErrors(std::move(*LastError), errorCorruptRecord());
@@ -208,241 +237,61 @@ bool TypeStreamMerger::remapIndex(TypeIndex &Idx) {
return false;
}
-//----------------------------------------------------------------------------//
-// Item records
-//----------------------------------------------------------------------------//
+bool TypeStreamMerger::remapTypeIndex(TypeIndex &Idx) {
+ // If we're mapping a pure index stream, then IndexMap only contains mappings
+ // from OldIdStream -> NewIdStream, in which case we will need to use the
+ // special mapping from OldTypeStream -> NewTypeStream which was computed
+ // externally. Regardless, we use this special map if and only if we are
+ // doing an id-only mapping.
+ if (DestTypeStream == nullptr)
+ return remapIndex(Idx, TypeLookup);
-Error TypeStreamMerger::visitKnownRecord(CVType &, FuncIdRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ParentScope);
- Success &= remapIndex(R.FunctionType);
- return writeIdRecord(R, Success);
+ assert(TypeLookup.empty());
+ return remapIndex(Idx, IndexMap);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, MemberFuncIdRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ClassType);
- Success &= remapIndex(R.FunctionType);
- return writeIdRecord(R, Success);
+bool TypeStreamMerger::remapItemIndex(TypeIndex &Idx) {
+ assert(DestIdStream);
+ return remapIndex(Idx, IndexMap);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, StringIdRecord &R) {
- return writeIdRecord(R, remapIndex(R.Id));
-}
+Error TypeStreamMerger::mergeTypeRecords(TypeTableBuilder &Dest,
+ const CVTypeArray &Types) {
+ DestTypeStream = &Dest;
-Error TypeStreamMerger::visitKnownRecord(CVType &, StringListRecord &R) {
- bool Success = true;
- for (TypeIndex &Str : R.StringIndices)
- Success &= remapIndex(Str);
- return writeIdRecord(R, Success);
+ return doit(Types);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, BuildInfoRecord &R) {
- bool Success = true;
- for (TypeIndex &Arg : R.ArgIndices)
- Success &= remapIndex(Arg);
- return writeIdRecord(R, Success);
-}
+Error TypeStreamMerger::mergeIdRecords(TypeTableBuilder &Dest,
+ ArrayRef<TypeIndex> TypeSourceToDest,
+ const CVTypeArray &Ids) {
+ DestIdStream = &Dest;
+ TypeLookup = TypeSourceToDest;
-Error TypeStreamMerger::visitKnownRecord(CVType &, UdtSourceLineRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.UDT);
- Success &= remapIndex(R.SourceFile);
- // FIXME: Translate UdtSourceLineRecord into UdtModSourceLineRecords in the
- // IPI stream.
- return writeIdRecord(R, Success);
+ return doit(Ids);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, UdtModSourceLineRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.UDT);
- Success &= remapIndex(R.SourceFile);
- return writeIdRecord(R, Success);
-}
+Error TypeStreamMerger::mergeTypesAndIds(TypeTableBuilder &DestIds,
+ TypeTableBuilder &DestTypes,
+ const CVTypeArray &IdsAndTypes) {
+ DestIdStream = &DestIds;
+ DestTypeStream = &DestTypes;
-//----------------------------------------------------------------------------//
-// Type records
-//----------------------------------------------------------------------------//
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, ModifierRecord &R) {
- return writeRecord(R, remapIndex(R.ModifiedType));
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, ProcedureRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ReturnType);
- Success &= remapIndex(R.ArgumentList);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, MemberFunctionRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ReturnType);
- Success &= remapIndex(R.ClassType);
- Success &= remapIndex(R.ThisType);
- Success &= remapIndex(R.ArgumentList);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &Type, ArgListRecord &R) {
- bool Success = true;
- for (TypeIndex &Arg : R.ArgIndices)
- Success &= remapIndex(Arg);
- if (auto EC = writeRecord(R, Success))
- return EC;
- return Error::success();
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, PointerRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ReferentType);
- if (R.isPointerToMember())
- Success &= remapIndex(R.MemberInfo->ContainingType);
- return writeRecord(R, Success);
+ return doit(IdsAndTypes);
}
-Error TypeStreamMerger::visitKnownRecord(CVType &, ArrayRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.ElementType);
- Success &= remapIndex(R.IndexType);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, ClassRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.FieldList);
- Success &= remapIndex(R.DerivationList);
- Success &= remapIndex(R.VTableShape);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, UnionRecord &R) {
- return writeRecord(R, remapIndex(R.FieldList));
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, EnumRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.FieldList);
- Success &= remapIndex(R.UnderlyingType);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, BitFieldRecord &R) {
- return writeRecord(R, remapIndex(R.Type));
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, VFTableShapeRecord &R) {
- return writeRecord(R, true);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, TypeServer2Record &R) {
- return writeRecord(R, true);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, LabelRecord &R) {
- return writeRecord(R, true);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, VFTableRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.CompleteClass);
- Success &= remapIndex(R.OverriddenVFTable);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &,
- MethodOverloadListRecord &R) {
- bool Success = true;
- for (OneMethodRecord &Meth : R.Methods)
- Success &= remapIndex(Meth.Type);
- return writeRecord(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownRecord(CVType &, FieldListRecord &R) {
- // Visit the members inside the field list.
- HadUntranslatedMember = false;
- FieldListBuilder.begin();
- if (auto EC = codeview::visitMemberRecordStream(R.Data, *this))
- return EC;
-
- // Write the record if we translated all field list members.
- TypeIndex DestIdx = Untranslated;
- if (!HadUntranslatedMember)
- DestIdx = FieldListBuilder.end();
- else
- FieldListBuilder.reset();
- addMapping(DestIdx);
-
- return Error::success();
-}
-
-//----------------------------------------------------------------------------//
-// Member records
-//----------------------------------------------------------------------------//
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
- NestedTypeRecord &R) {
- return writeMember(R, remapIndex(R.Type));
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &, OneMethodRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.Type);
- return writeMember(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
- OverloadedMethodRecord &R) {
- return writeMember(R, remapIndex(R.MethodList));
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
- DataMemberRecord &R) {
- return writeMember(R, remapIndex(R.Type));
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
- StaticDataMemberRecord &R) {
- return writeMember(R, remapIndex(R.Type));
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
- EnumeratorRecord &R) {
- return writeMember(R, true);
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &, VFPtrRecord &R) {
- return writeMember(R, remapIndex(R.Type));
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &, BaseClassRecord &R) {
- return writeMember(R, remapIndex(R.Type));
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
- VirtualBaseClassRecord &R) {
- bool Success = true;
- Success &= remapIndex(R.BaseType);
- Success &= remapIndex(R.VBPtrType);
- return writeMember(R, Success);
-}
-
-Error TypeStreamMerger::visitKnownMember(CVMemberRecord &,
- ListContinuationRecord &R) {
- return writeMember(R, remapIndex(R.ContinuationIndex));
-}
-
-Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
- // We failed to translate a type. Translate this index as "not translated".
- addMapping(TypeIndex(SimpleTypeKind::NotTranslated));
- return errorCorruptRecord();
-}
-
-Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
- assert(IndexMap.empty());
+Error TypeStreamMerger::doit(const CVTypeArray &Types) {
LastError = Error::success();
- if (auto EC = codeview::visitTypeStream(Types, *this, Handler))
+ // We don't want to deserialize records. I guess this flag is poorly named,
+ // but it really means "Don't deserialize records before switching on the
+ // concrete type.
+ // FIXME: We can probably get even more speed here if we don't use the visitor
+ // pipeline here, but instead write the switch ourselves. I don't think it
+ // would buy us much since it's already pretty fast, but it's probably worth
+ // a few cycles.
+ if (auto EC =
+ codeview::visitTypeStream(Types, *this, VDS_BytesExternal, Handler))
return EC;
// If we found bad indices but no other errors, try doing another pass and see
@@ -458,7 +307,8 @@ Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
NumBadIndices = 0;
CurIndex = TypeIndex(TypeIndex::FirstNonSimpleIndex);
- if (auto EC = codeview::visitTypeStream(Types, *this, Handler))
+ if (auto EC =
+ codeview::visitTypeStream(Types, *this, VDS_BytesExternal, Handler))
return EC;
assert(NumBadIndices <= BadIndicesRemaining &&
@@ -469,18 +319,32 @@ Error TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
}
}
- IndexMap.clear();
-
Error Ret = std::move(*LastError);
LastError.reset();
return Ret;
}
-Error llvm::codeview::mergeTypeStreams(TypeTableBuilder &DestIdStream,
- TypeTableBuilder &DestTypeStream,
+Error llvm::codeview::mergeTypeRecords(TypeTableBuilder &Dest,
SmallVectorImpl<TypeIndex> &SourceToDest,
TypeServerHandler *Handler,
- const CVTypeArray &Types) {
- return TypeStreamMerger(DestIdStream, DestTypeStream, SourceToDest, Handler)
- .mergeStream(Types);
+ const CVTypeArray &Types) {
+ TypeStreamMerger M(SourceToDest, Handler);
+ return M.mergeTypeRecords(Dest, Types);
+}
+
+Error llvm::codeview::mergeIdRecords(TypeTableBuilder &Dest,
+ ArrayRef<TypeIndex> TypeSourceToDest,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Ids) {
+ TypeStreamMerger M(SourceToDest, nullptr);
+ return M.mergeIdRecords(Dest, TypeSourceToDest, Ids);
+}
+
+Error llvm::codeview::mergeTypeAndIdRecords(
+ TypeTableBuilder &DestIds, TypeTableBuilder &DestTypes,
+ SmallVectorImpl<TypeIndex> &SourceToDest, TypeServerHandler *Handler,
+ const CVTypeArray &IdsAndTypes) {
+
+ TypeStreamMerger M(SourceToDest, Handler);
+ return M.mergeTypesAndIds(DestIds, DestTypes, IdsAndTypes);
}
diff --git a/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/lib/DebugInfo/CodeView/TypeTableCollection.cpp
index a18710d6ab52..699694fde928 100644
--- a/lib/DebugInfo/CodeView/TypeTableCollection.cpp
+++ b/lib/DebugInfo/CodeView/TypeTableCollection.cpp
@@ -24,8 +24,7 @@ static void error(Error &&EC) {
consumeError(std::move(EC));
}
-TypeTableCollection::TypeTableCollection(
- ArrayRef<MutableArrayRef<uint8_t>> Records)
+TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records)
: Records(Records), Database(Records.size()) {}
Optional<TypeIndex> TypeTableCollection::getFirst() {
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp
index 8e7c6c43d1a2..5ed55ce4c0dc 100644
--- a/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -60,12 +60,15 @@ typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
uint64_t llvm::getRelocatedValue(const DataExtractor &Data, uint32_t Size,
- uint32_t *Off, const RelocAddrMap *Relocs) {
+ uint32_t *Off, const RelocAddrMap *Relocs,
+ uint64_t *SectionIndex) {
if (!Relocs)
return Data.getUnsigned(Off, Size);
RelocAddrMap::const_iterator AI = Relocs->find(*Off);
if (AI == Relocs->end())
return Data.getUnsigned(Off, Size);
+ if (SectionIndex)
+ *SectionIndex = AI->second.SectionIndex;
return Data.getUnsigned(Off, Size) + AI->second.Value;
}
@@ -287,6 +290,15 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH,
getStringSection(), isLittleEndian());
}
+DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
+ // FIXME: Improve this for the case where this DWO file is really a DWP file
+ // with an index - use the index for lookup instead of a linear search.
+ for (const auto &DWOCU : dwo_compile_units())
+ if (DWOCU->getDWOId() == Hash)
+ return DWOCU.get();
+ return nullptr;
+}
+
DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) {
parseCompileUnits();
if (auto *CU = CUs.getUnitForOffset(Offset))
@@ -897,28 +909,81 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
return InliningInfo;
}
+std::shared_ptr<DWARFContext>
+DWARFContext::getDWOContext(StringRef AbsolutePath) {
+ if (auto S = DWP.lock()) {
+ DWARFContext *Ctxt = S->Context.get();
+ return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
+ }
+
+ std::weak_ptr<DWOFile> *Entry = &DWOFiles[AbsolutePath];
+
+ if (auto S = Entry->lock()) {
+ DWARFContext *Ctxt = S->Context.get();
+ return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
+ }
+
+ SmallString<128> DWPName;
+ Expected<OwningBinary<ObjectFile>> Obj = [&] {
+ if (!CheckedForDWP) {
+ (getFileName() + ".dwp").toVector(DWPName);
+ auto Obj = object::ObjectFile::createObjectFile(DWPName);
+ if (Obj) {
+ Entry = &DWP;
+ return Obj;
+ } else {
+ CheckedForDWP = true;
+ // TODO: Should this error be handled (maybe in a high verbosity mode)
+ // before falling back to .dwo files?
+ consumeError(Obj.takeError());
+ }
+ }
+
+ return object::ObjectFile::createObjectFile(AbsolutePath);
+ }();
+
+ if (!Obj) {
+ // TODO: Actually report errors helpfully.
+ consumeError(Obj.takeError());
+ return nullptr;
+ }
+
+ auto S = std::make_shared<DWOFile>();
+ S->File = std::move(Obj.get());
+ S->Context = llvm::make_unique<DWARFContextInMemory>(*S->File.getBinary());
+ *Entry = S;
+ auto *Ctxt = S->Context.get();
+ return std::shared_ptr<DWARFContext>(std::move(S), Ctxt);
+}
+
static Error createError(const Twine &Reason, llvm::Error E) {
return make_error<StringError>(Reason + toString(std::move(E)),
inconvertibleErrorCode());
}
-/// Returns the address of symbol relocation used against. Used for futher
-/// relocations computation. Symbol's section load address is taken in account if
-/// LoadedObjectInfo interface is provided.
-static Expected<uint64_t>
-getSymbolAddress(const object::ObjectFile &Obj, const RelocationRef &Reloc,
- const LoadedObjectInfo *L,
- std::map<SymbolRef, uint64_t> &Cache) {
- uint64_t Ret = 0;
+/// SymInfo contains information about symbol: it's address
+/// and section index which is -1LL for absolute symbols.
+struct SymInfo {
+ uint64_t Address;
+ uint64_t SectionIndex;
+};
+
+/// Returns the address of symbol relocation used against and a section index.
+/// Used for futher relocations computation. Symbol's section load address is
+static Expected<SymInfo> getSymbolInfo(const object::ObjectFile &Obj,
+ const RelocationRef &Reloc,
+ const LoadedObjectInfo *L,
+ std::map<SymbolRef, SymInfo> &Cache) {
+ SymInfo Ret = {0, (uint64_t)-1LL};
object::section_iterator RSec = Obj.section_end();
object::symbol_iterator Sym = Reloc.getSymbol();
- std::map<SymbolRef, uint64_t>::iterator CacheIt = Cache.end();
+ std::map<SymbolRef, SymInfo>::iterator CacheIt = Cache.end();
// First calculate the address of the symbol or section as it appears
// in the object file
if (Sym != Obj.symbol_end()) {
bool New;
- std::tie(CacheIt, New) = Cache.insert({*Sym, 0});
+ std::tie(CacheIt, New) = Cache.insert({*Sym, {0, 0}});
if (!New)
return CacheIt->second;
@@ -934,12 +999,15 @@ getSymbolAddress(const object::ObjectFile &Obj, const RelocationRef &Reloc,
SectOrErr.takeError());
RSec = *SectOrErr;
- Ret = *SymAddrOrErr;
+ Ret.Address = *SymAddrOrErr;
} else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
- Ret = RSec->getAddress();
+ Ret.Address = RSec->getAddress();
}
+ if (RSec != Obj.section_end())
+ Ret.SectionIndex = RSec->getIndex();
+
// If we are given load addresses for the sections, we need to adjust:
// SymAddr = (Address of Symbol Or Section in File) -
// (Address of Section in File) +
@@ -949,7 +1017,7 @@ getSymbolAddress(const object::ObjectFile &Obj, const RelocationRef &Reloc,
// we need to perform the same computation.
if (L && RSec != Obj.section_end())
if (uint64_t SectionLoadAddress = L->getSectionLoadAddress(*RSec))
- Ret += SectionLoadAddress - RSec->getAddress();
+ Ret.Address += SectionLoadAddress - RSec->getAddress();
if (CacheIt != Cache.end())
CacheIt->second = Ret;
@@ -989,8 +1057,8 @@ Error DWARFContextInMemory::maybeDecompress(const SectionRef &Sec,
}
DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
- const LoadedObjectInfo *L)
- : IsLittleEndian(Obj.isLittleEndian()),
+ const LoadedObjectInfo *L)
+ : FileName(Obj.getFileName()), IsLittleEndian(Obj.isLittleEndian()),
AddressSize(Obj.getBytesInAddress()) {
for (const SectionRef &Section : Obj.sections()) {
StringRef name;
@@ -1008,7 +1076,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
// Try to obtain an already relocated version of this section.
// Else use the unrelocated section from the object file. We'll have to
// apply relocations ourselves later.
- if (!L || !L->getLoadedSectionContents(*RelocatedSection,data))
+ if (!L || !L->getLoadedSectionContents(*RelocatedSection, data))
Section.getContents(data);
if (auto Err = maybeDecompress(Section, name, data)) {
@@ -1047,7 +1115,7 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
// If the section we're relocating was relocated already by the JIT,
// then we used the relocated version above, so we do not need to process
// relocations for it now.
- if (L && L->getLoadedSectionContents(*RelocatedSection,RelSecData))
+ if (L && L->getLoadedSectionContents(*RelocatedSection, RelSecData))
continue;
// In Mach-o files, the relocations do not need to be applied if
@@ -1091,29 +1159,30 @@ DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
if (Section.relocation_begin() == Section.relocation_end())
continue;
- std::map<SymbolRef, uint64_t> AddrCache;
+ // Symbol to [address, section index] cache mapping.
+ std::map<SymbolRef, SymInfo> AddrCache;
for (const RelocationRef &Reloc : Section.relocations()) {
// FIXME: it's not clear how to correctly handle scattered
// relocations.
if (isRelocScattered(Obj, Reloc))
continue;
- Expected<uint64_t> SymAddrOrErr =
- getSymbolAddress(Obj, Reloc, L, AddrCache);
- if (!SymAddrOrErr) {
- errs() << toString(SymAddrOrErr.takeError()) << '\n';
+ Expected<SymInfo> SymInfoOrErr = getSymbolIn